我正在尝试为教育目的构建一个简单的游戏,并且在以正确的坐标绘制对象时遇到问题。
我有想要利用的svg飞船,因此我使用此工具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>
答案 0 :(得分:2)
一个好消息是,您可以像我在下一个演示中一样使用Path2D在画布中绘制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>