svg - 在错误的坐标中绘制翻译路径

标签 svg canvas

我正在尝试构建一个用于教育目的的简单游戏,但在正确坐标中绘制对象时遇到问题。

我想要使用 svg 宇宙飞船,所以我使用此工具将其转换为 Canvas 路径系统 SVG to Canvas converter .

由于 svg 最初是在 1000x1000 平面上设计的,因此我必须应用比例来达到所需的尺寸

// calculate scale, if size (r) has to be 40px then 40px / original size (1000) = 0.04;
var size = r / 1000;
ctx.scale(size, size); // apply desired size

它似乎有效,但当涉及到在设定坐标(x,y)中渲染它时,它显然是偏离目标的。

在演示中,您可以看到船舶正在旋转并移动到应有的位置之外,而且不成比例似乎会根据位置而变化,这显然意味着出现了问题。

也许有人可以找到原因以及我该如何解决它? ofc 的目标是将船舶渲染在辅助框的中心。

这是演示代码:

var cvs = document.querySelector('canvas'),
	ctx = cvs.getContext('2d'),
	w = cvs.width = 1000,
	h = cvs.height = 1000,
	helper = document.querySelector('.helper');

var ship = function(x, y, r, a) {
	var size = r / 1000; // calculate scale, if size (r) has to be 40px then 40px / original size (1000) = 0.04;
	x -= r / 2; // go back half of its width to center ship on passed x coord
	y -= r / 2; // go back half of its height to center ship on passed y coord
	
	/* draw original ship ----> */
	
	ctx.save();
	
	ctx.translate(x, y);
	ctx.scale(size, size); // apply desired size
	ctx.rotate((a + 90) * Math.PI / 180); // rotate ship on its center
	ctx.translate(-x, -y);
	
	ctx.beginPath();
	ctx.moveTo(341.4,856.1);
	ctx.lineTo(173.2,881.8000000000001);
	ctx.bezierCurveTo(159.79999999999998,883.8000000000001,146.5,877.7,139.39999999999998,866.2);
	ctx.lineTo(76.69999999999997,764.2);
	ctx.bezierCurveTo(73.19999999999997,758.5,71.59999999999998,752,71.79999999999997,745.6);
	ctx.bezierCurveTo(71.79999999999997,745.1,71.69999999999997,744.5,71.69999999999997,744);
	ctx.lineTo(71.69999999999997,528.2);
	ctx.bezierCurveTo(71.69999999999997,509.6,86.79999999999997,494.50000000000006,105.39999999999998,494.50000000000006);
	ctx.bezierCurveTo(123.99999999999997,494.50000000000006,139.09999999999997,509.6000000000001,139.09999999999997,528.2);
	ctx.lineTo(139.09999999999997,617.7);
	ctx.lineTo(273.79999999999995,377.80000000000007);
	ctx.lineTo(341.49999999999994,493.30000000000007);
	ctx.lineTo(341.49999999999994,856.1);
	ctx.closePath();
	
	ctx.moveTo(894.7,494.5);
	ctx.bezierCurveTo(876.1,494.5,861,509.6,861,528.2);
	ctx.lineTo(861,617.7);
	ctx.lineTo(726.3,377.8);
	ctx.lineTo(658.5999999999999,493.3);
	ctx.lineTo(658.5999999999999,856.1);
	ctx.lineTo(826.8,881.8000000000001);
	ctx.bezierCurveTo(840.1999999999999,883.8000000000001,853.5,877.7,860.5999999999999,866.1);
	ctx.lineTo(923.3,764.1);
	ctx.bezierCurveTo(926.8,758.4,928.4,751.9,928.1999999999999,745.5);
	ctx.bezierCurveTo(928.1999999999999,745,928.3,744.4,928.3,743.9);
	ctx.lineTo(928.3,528.2);
	ctx.bezierCurveTo(928.3,509.6,913.3,494.5,894.7,494.5);
	ctx.closePath();
	
	ctx.moveTo(591.2,857.6);
	ctx.lineTo(533.7,900.5);
	ctx.lineTo(533.7,956.4);
	ctx.bezierCurveTo(533.7,975,518.6,990.1,500.00000000000006,990.1);
	ctx.bezierCurveTo(481.40000000000003,990.1,466.30000000000007,975,466.30000000000007,956.4);
	ctx.lineTo(466.30000000000007,900.5);
	ctx.lineTo(408.80000000000007,857.6);
	ctx.lineTo(408.80000000000007,484.2);
	ctx.bezierCurveTo(408.80000000000007,478.2,407.20000000000005,472.3,404.20000000000005,467.2);
	ctx.lineTo(312.00000000000006,309.79999999999995);
	ctx.lineTo(470.6,27.2);
	ctx.bezierCurveTo(476.6,16.6,487.8,10,500,10);
	ctx.bezierCurveTo(512.2,10,523.4,16.6,529.4,27.2);
	ctx.lineTo(688.0999999999999,309.8);
	ctx.lineTo(595.8999999999999,467.20000000000005);
	ctx.bezierCurveTo(592.8999999999999,472.40000000000003,591.2999999999998,478.20000000000005,591.2999999999998,484.20000000000005);
	ctx.lineTo(591.2999999999998,857.6);
	ctx.closePath();
	
	ctx.moveTo(591,318.2);
	ctx.bezierCurveTo(605.3,306.4,607.4,285.09999999999997,595.5,270.8);
	ctx.bezierCurveTo(591.6,266.1,555.8,224.60000000000002,500.8,224.60000000000002);
	ctx.bezierCurveTo(446.3,224.60000000000002,409.1,265.40000000000003,405,270.1);
	ctx.bezierCurveTo(392.7,284.1,394.1,305.5,408.1,317.70000000000005);
	ctx.bezierCurveTo(414.5,323.30000000000007,422.40000000000003,326.1,430.3,326.1);
	ctx.bezierCurveTo(439.6,326.1,448.90000000000003,322.20000000000005,455.5,314.70000000000005);
	ctx.bezierCurveTo(461.2,308.40000000000003,480.4,292.1,500.8,292.1);
	ctx.bezierCurveTo(524.7,292.1,543.6,313.8,543.6,313.8);
	ctx.bezierCurveTo(555.5,328,576.7,330.1,591,318.2);
	ctx.closePath();
	
	ctx.fillStyle = '#000';
	ctx.strokeStyle = '#000';
	ctx.lineWidth = 1;
	
	ctx.fill();
	ctx.stroke();
	ctx.restore();
	
	/* <---- draw original ship */
};

var c = { x: 100, y: 100, a: 270, r: 40 };

var rotator = 1;

var render = function() {
	ctx.clearRect(0, 0, w, h);
	ctx.fillStyle = '#ccc';
	ctx.fillRect(0, 0, w, h);

	ship(c.x, c.y, c.r, c.a);
	
	c.x += rotator;
	c.y += rotator;
	c.a += rotator;
	
	if(c.x >= 950 || c.y >= 950 || c.x <= 50 || c.y <= 50) {
		rotator *= -1;
	}
	
	/* helper debug section ----> */
	ctx.save();
	ctx.beginPath();
	ctx.moveTo(c.x, 0);
	ctx.lineTo(c.x, 1000);
	ctx.closePath();
	ctx.stroke();
	ctx.beginPath();
	ctx.moveTo(0, c.y);
	ctx.lineTo(1000, c.y);
	ctx.closePath();
	ctx.stroke();
	ctx.beginPath();
	ctx.moveTo(c.x, c.y);
	ctx.lineTo(c.x, c.y - 20);
	ctx.lineTo(c.x - 20, c.y - 20);
	ctx.lineTo(c.x - 20, c.y);
	ctx.lineTo(c.x - 20, c.y + 20);
	ctx.lineTo(c.x, c.y + 20);
	ctx.lineTo(c.x + 20, c.y + 20);
	ctx.lineTo(c.x + 20, c.y);
	ctx.lineTo(c.x + 20, c.y - 20);
	ctx.lineTo(c.x, c.y - 20);
	ctx.closePath();
	ctx.stroke();
	ctx.restore();
	/* <---- helper debug section */

	requestAnimationFrame(render);
};

render();
canvas {
	position:absolute;
	top:0;
	left:0;
}
<canvas></canvas>

最佳答案

值得一提的是,您可以使用 Path2D 在 Canvas 中绘制 svg 路径,就像我在下一个演示中所做的那样。我也重新计算了你的路径。您使用的路径是 1000/1000 单位。我重新计算了您的路径,使其在 x 和 y 方向上均从 -500 开始,并将中心放在原点:点 {x:0,y:0}。

let svgPath =`M-158.60000000000002,356.1L-326.8,381.79999999999995C-340.2,383.79999999999995,-353.5,377.70000000000005,-360.6,366.20000000000005L-423.3,264.20000000000005C-426.8,258.5,-428.4,252,-428.2,245.60000000000002,-428.2,245.10000000000002,-428.3,244.5,-428.3,244L-428.3,28.200000000000045C-428.3,9.600000000000023,-413.2,-5.5,-394.6,-5.5,-376,-5.5,-360.9,9.600000000000023,-360.99,28.200000000000045L-360.9,117.70000000000005,-226.2,-122.19999999999999,-158.5,-6.699999999999989,-158.5,356.1
M394.70000000000005,-5.5C376.1,-5.5,361,9.600000000000023,361,28.200000000000045L361,117.70000000000005,226.29999999999995,-122.19999999999999,158.69000000000005,-6.699999999999989,158.60000000000002,356.1,326.79999999999995,381.79999999999995C340.20000000000005,383.79999999999995,353.5,377.70000000000005,360.6,366.1L423.29999999999995,264.1C426.79999999999995,258.4,428.4,251.89999999999998,428.20000000000005,245.5,428.20000000000005,245,428.29999999999995,244.39999999999998,428.29999999999995,243.89999999999998,428.29999999999995,9.600000000000023,413.29999999999995,-5.5,394.70000000000005,-5.5z
M91.20000000000005,357.6L33.700000000000045,400.5,33.700000000000045,456.4C33.700000000000045,475,18.600000000000023,490.1,0,490.1,-18.600000000000023,490.1,-33.69999999999999,475,-33.69999999999999,456.4L-33.69999999999999,400.5,-91.19999999999999,357.6,-91.13,-15.800000000000011C-91.19999999999999,-21.80000000000001,-92.80000000000001,-27.69999999999999,-95.80000000000001,-32.80000000000001L-188,-190.2,-29.399999999999977,-472.8C-23.399999999999977,-483.4,-12.199999999999989,-490,0,-490,12.200000000000045,-490,23.399999999999977,-483.4,29.399999999999977,-472.8L188.10000000000002,-190.2,95.89999999999998,-32.80000000000001C92.89999999999998,-27.569999999999993,91.29999999999995,-21.80000000000001,91.29999999999995,-15.800000000000011L91.29999999999995,357.6z
M91,-181.8C105.29999999999995,-193.60000000000002,107.39999999999998,-214.89999999999998,95.5,-229.2,91.60000000000002,-233.89999999999998,55.799999999999955,-275.4,0.8000000000000114,-275.4,-53.69999999999999,-275.4,-90.89999999999998,-234.60000000000002,-95,-229.89999999999998,-107.30000000000001,-215.89999999999998,-105.89999999999998,-194.5,-91.89999999999998,-182.3,-85.5,-176.7,-77.60000000000002,-173.89999999999998,-69.69999999999999,-173.89999999999998,-60.39999999999998,-173.89999999999998,-51.10000000000002,-177.8,-44.5,-185.3,-38.80000000000001,-191.60000000000002,-19.600000000000023,-207.89999999999998,0.8000000000000114,-207.89999999999998,24.700000000000045,-207.89999999999998,43.60000000000002,-186.2,43.60000000000002,-186.2,55.5,-172,76.70000000000005,-169.89999999999998,91,-181.8z`;


var cvs = document.querySelector('canvas'),
	ctx = cvs.getContext('2d'),
	w = cvs.width = window.innerWidth,
	h = cvs.height = window.innerHeight;
ctx.fillStyle = "black";
let shuttle = new Path2D(svgPath);


let angle = 0;
let x = 0;
let y = 0;
let increment = 1


let the_scale = .1;
//helper size
//1000 is the size of the svg path
let hs = (1000 * the_scale) / 2;


function frame(){
  window.requestAnimationFrame(frame);
  ctx.clearRect(0, 0, w,h )
  angle += increment/100;
  x+=increment;
  if(y < h + hs){y+=increment;}else{y = -hs; x=-hs;}
  ctx.save();
  ctx.fillStyle="#333"
  ctx.translate(x,y);
  ctx.scale(the_scale,the_scale);
  ctx.rotate(angle);
  ctx.fill(shuttle);
 
  ctx.restore();
  
  helper(x,y)
}

frame();


function helper(x,y){
  ctx.strokeStyle="red"
  ctx.beginPath();
	ctx.moveTo(x, 0);
	ctx.lineTo(x, h);
	ctx.closePath();
	ctx.stroke();
	ctx.beginPath();
	ctx.moveTo(0, y);
	ctx.lineTo(w, y);
	ctx.closePath();
	ctx.stroke();
	ctx.beginPath();
	ctx.moveTo(x, y);
	ctx.lineTo(x, y - hs);
	ctx.lineTo(x - hs, y - hs);
	ctx.lineTo(x - hs, y);
	ctx.lineTo(x - hs, y + hs);
	ctx.lineTo(x, y + hs);
	ctx.lineTo(x + hs, y + hs);
	ctx.lineTo(x + hs, y);
	ctx.lineTo(x + hs, y - hs);
	ctx.lineTo(x, y - hs);
	ctx.closePath();
	ctx.stroke();
}
*{margin:0;padding:0}
canvas{background:#d9d9d9;}
<canvas></canvas>

关于svg - 在错误的坐标中绘制翻译路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54824250/

相关文章:

html - SVG 在表格 td 内获取全高度

xml - SVG id 有效字符的 ISO 表

javascript - SketchUp -> Canvas

javascript - getImageData 总是返回 0

javascript - ThreeJS 将体素放置在选定尺寸的网格上

Android - 具有硬件加速和抗锯齿的画线会导致伪影

javascript - 将 SVG 文件包含在 HTML 中,并且仍然能够对它们应用样式?

svg - Inkscape:持久对齐

javascript - CSS/JS/Jquery 中的 SVG 发光效果

javascript - 在 Javascript 中使用按钮引用 Canvas