假设我们有一张虚拟地图,如下所示:
这只是一个例子,地图可以有不同的内容和/或大小。让我们假设我们知道每个房子的位置,它们位于圆形,矩形或多边形中。让我们进一步假设我们想要一个步行动画"从任意的房子1到任意的房子2。
通过"动画散步"我的意思是从house1开始到house2结束的道路应该暂时被着色,让我们说,以连续的方式变红,也就是说,动画应该得到以下参数:
道路部分不应立即着色,而应基于时间变量。道路最初不应该着色,然后在经过t时间之后,道路的t /时间应该是彩色的,并且房屋1的方向 - > house2。
我考虑过使用地图,如下所示:
<img id="img-map" src="/img/maps/mymap.png" alt="" usemap="#Map" />
<map name="Map" id="Map">
<area alt="" title="Babuka" href="" shape="poly" coords="189,433,179,456,185,479,208,484,235,481,236,459,217,439" />
<area alt="" title="Sheldonka" href="" shape="poly" coords="304,277,297,294,301,309,321,314,341,312,341,296,326,279" />
<area alt="" title="Herceg" href="" shape="poly" coords="95,278,114,287,128,283,128,275,122,267,104,262,95,269" />
<area alt="" title="Babuka elment Sheldonkahoz" href="#" shape="poly" coords="220,494,227,500,247,494,268,486,283,477,305,468,321,458,336,451,345,444,355,429,357,416,353,403,345,389,329,359,312,335,307,328,305,326,313,327,321,327,329,326,335,326,337,317,323,317,313,318,302,320,293,319,293,327,300,333,306,339,310,351,320,364,327,372,333,384,337,392,341,400,342,407,345,413,345,417,345,423,345,428,339,439" />
</map>
可以为区域创建事件处理程序,这是一件非常好的事情,因为能够捕获房屋的点击/悬停等事件会很酷,但我们如何处理上述动画呢?我想暂时在地图上显示一个画布,但这似乎过于hacky。此外,我考虑将每个房屋前面的可能开始/结束点保存到道路上,因此,至少在动画开始时,系统将知道从哪里开始和到哪里结束。除了道路模式(可能是颜色)之外,知道这两个点,可以确定弧。基于弧,其长度和总面积(像素数)也可以确定。如果我们知道为动画长度指定的总长度和时间,那么动画可以是使用临时像素着色的动画。
这可以使用地图并在动画完成时暂时将画布放在其上或仅使用画布来完成。考虑到预期的效果,如何解决这个问题?
答案 0 :(得分:1)
首先确定您房屋之间的道路
查看之前的Stackoverflow Q&A,其中显示了如何确定沿着道路穿过航路点的一组曲线。这组曲线是一个html5画布路径。
然后通过沿该路径计算一组统一的航路点来行驶
然后查看之前的Stackoverflow Q&A,其中显示了如何以均匀的速度沿着路径行进。
以下是示例代码和演示:
此示例显示如何以均匀的速度沿路径行进。
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var nextTime=0;
var delay=1000/60*3;
var ptIndex=0;
var linepts=[{x:50,y:75},{x:150,y:50},{x:200,y:100},{x:100,y:175},{x:250,y:250}];
var points=[];
for(var i=1;i<linepts.length;i++){
points=points.concat(plotLinePoints(linepts[i-1],linepts[i],5));
}
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png";
function start(){
var last=linepts.length-1;
unfilledStroke(linepts,25);
ctx.drawImage(img,linepts[0].x-img.width-15,linepts[0].y-img.height);
ctx.drawImage(img,linepts[last].x+img.width/2,linepts[last].y);
requestAnimationFrame(animatePath);
}
function animatePath(time){
ctx.beginPath();
ctx.moveTo(points[ptIndex].x, points[ptIndex].y);
ctx.lineTo(points[ptIndex+1].x, points[ptIndex+1].y);
ctx.lineWidth=5;
ctx.strokeStyle='red';
ctx.stroke();
ptIndex++;
if(ptIndex<points.length-1){
requestAnimationFrame(animatePath);
}
}
function path(pts){
ctx.beginPath();
ctx.moveTo(pts[0].x,pts[0].y);
for(var i=1;i<pts.length;i++){
ctx.lineTo(pts[i].x,pts[i].y);
}
}
function unfilledStroke(pts,linewidth){
ctx.lineWidth=linewidth;
ctx.lineCap='round';
ctx.lineJoin='round';
path(pts);
ctx.stroke();
//
ctx.globalCompositeOperation='destination-out';
ctx.lineWidth=linewidth/2;
ctx.lineCap='round';
path(pts);
ctx.stroke();
ctx.globalCompositeOperation='source-over';
}
function plotLinePoints(s,e,pctIncrement){
var dx=e.x-s.x;
var dy=e.y-s.y;
var pts=[s];
for(var p=pctIncrement;p<100;p+=pctIncrement){
pts.push({
x:s.x+dx*p/100,
y:s.y+dy*p/100
});
}
pts.push(e);
return(pts);
}
&#13;
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
&#13;
<canvas id="canvas" width=400 height=300></canvas>
&#13;