我一直在寻找一种明确的方式,可以将形状从圆形转变为三角形或矩形,反之亦然。我认为可以存储该形状并更改其属性以进行转换。
基本上,我的问题是,如何绘制一个圆形,然后在单击按钮时将其动画变成三角形?使用canvas形状是否可行?
谢谢!
基本上,我的问题是,如何绘制一个圆形,然后在单击按钮时将其动画变成三角形?使用canvas形状是否可行?
谢谢!
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
// change sideCount to the # of poly sides desired
//
var sideCount=3;
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.lineWidth=2;
ctx.fillStyle=randomColor();
var PI2=Math.PI*2;
var cx=150;
var cy=150;
var radius=100;
var xx=function(a){return(cx+radius*Math.cos(a));}
var yy=function(a){return(cy+radius*Math.sin(a));}
var lerp=function(a,b,x){ return(a+x*(b-a)); }
var sides=[];
for(var i=0;i<sideCount;i++){
sides.push(makeSide(i,sideCount));
}
var percent=0;
var percentDirection=0.50;
$("#toShape").click(function(){
percentDirection=-0.50;
})
$("#toCircle").click(function(){
percentDirection=0.50;
})
animate();
// functions
function animate(){
requestAnimationFrame(animate);
drawSides(percent);
percent+=percentDirection;
if(percent>100){percent=100;}
if(percent<0){percent=0;}
}
function drawSides(pct,color){
ctx.clearRect(0,0,canvas.width,canvas.height);
if(pct==100){
ctx.beginPath();
ctx.arc(cx,cy,radius,0,PI2);
ctx.closePath();
ctx.fill();
}else{
ctx.beginPath();
ctx.moveTo(sides[0].x0,sides[0].y0);
for(var i=0;i<sideCount;i++){
var side=sides[i];
var cpx=lerp(side.midX,side.cpX,pct/100);
var cpy=lerp(side.midY,side.cpY,pct/100);
ctx.quadraticCurveTo(cpx,cpy,side.x2,side.y2);
}
ctx.fill();
}
}
function makeSide(n,sideCount){
var sweep=PI2/sideCount;
var sAngle=sweep*(n-1);
var eAngle=sweep*n;
var x0=xx(sAngle);
var y0=yy(sAngle);
var x1=xx((eAngle+sAngle)/2);
var y1=yy((eAngle+sAngle)/2);
var x2=xx(eAngle);
var y2=yy(eAngle);
var dx=x2-x1;
var dy=y2-y1;
var a=Math.atan2(dy,dx);
var midX=lerp(x0,x2,0.50);
var midY=lerp(y0,y2,0.50);
var cpX=2*x1-x0/2-x2/2;
var cpY=2*y1-y0/2-y2/2;
return({
x0:x0, y0:y0,
x2:x2, y2:y2,
midX:midX, midY:midY,
cpX:cpX, cpY:cpY,
color:randomColor()
});
}
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
}); // end $(function(){});
</script>
</head>
<body>
<button id="toShape">Animate to Shape</button>
<button id="toCircle">Animate to Circle</button><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
您可能想使用 Raphael (https://dmitrybaranovskiy.github.io/raphael/) 或类似的库来为您处理此操作。Raphael 网站包含许多类似于您描述的案例示例。
DEMO(点击圆圈以使它们动画)
对于从圆形到矩形的过渡效果,实现起来非常容易,只需动画化边框半径即可:
CSS:
#rec {
float:left;
width:200px;
height:200px;
background:gold;
border-radius:50%;
-webkit-transition: border-radius 1s, width 1s;
cursor:pointer;
}
#rec.animate {
border-radius:0%;
width:300px;
}
/*CIRCLE TO TRIANGLE 1 */
#tr1{
float:right;
position:relative;
cursor:pointer;
width:200px;
height:200px;
}
#tr1:before, #tr1:after{
content:'';
position:absolute;
}
#tr1:before{
top:0; left:0;
background:gold;
border-radius:50%;
width:100%;
height:100%;
-webkit-transition: width 1s, height 1s, left 1s, top 1s;
}
#tr1:after{
left:50%;
top:50%;
border-left:0px solid transparent;
border-right:0px solid transparent;
border-bottom:0px solid gold;
-webkit-transition: border-left 1s, border-right 1s, border-bottom 1s,left 1s, top 1s;
}
#tr1.animate:before{
width:0;
height:0;
top:50%; left:50%;
}
#tr1.animate:after{
top:0; left:0;
border-left:100px solid transparent;
border-right:100px solid transparent;
border-bottom:200px solid gold;
}
/*CIRCLE TO TRIANGLE 2 */
#tr2{
float:right;
position:relative;
cursor:pointer;
width:200px;
height:200px;
}
#tr2:before, #tr2:after{
content:'';
position:absolute;
}
#tr2:before{
top:0; left:0;
background:gold;
border-radius:50%;
width:100%;
height:100%;
-webkit-transition: width 1s, height 1s, left 1s, top 1s;
}
#tr2:after{
left:20px;
top:0;
border-left:80px solid transparent;
border-right:80px solid transparent;
border-bottom:160px solid gold;
-webkit-transition: border-left 1s, border-right 1s, border-bottom 1s,left 1s, top 1s;
z-index:-1;
}
#tr2.animate:before{
width:0;
height:0;
top:50%; left:50%;
}
#tr2.animate:after{
top:0; left:0;
border-left:100px solid transparent;
border-right:100px solid transparent;
border-bottom:200px solid gold;
}
我将授予@rje,因为他让我朝着正确的方向前进,并且在所有的努力之后,我意识到我的问题没有具体说明我的问题。
首先,我将解释我实际上正在寻找什么:基本上,在画布上创建一个“形状”时,很容易将其用作蒙版。通过蒙版,我指的是,假设您在画布中央绘制一个圆形,它保持透明,但画布填充有某种颜色。 直接使用raphael js来完成这项任务有点奇怪,直到你掌握了它,因为它实际上是svg,并且有不同的规则。您必须绘制一个外部路径,该路径将与纸张(raphael“画布”)匹配,并且一个内部路径将保持透明。对我来说,挑战是使其也具有响应性,但我最终成功地使用类似于此的东西实现了它
var tw; // canvas width
var th; // canvas height
var tr; // radius of circle, in my case calculated dynamically smth like (th - 20) / 2
var outerpath = "M0,0L" + tw + ",0L" + tw + "," + th + "L0," + th + "L0,0z";
var innerpath = "M" + (tw/2) + "," + (th/2 - tr) + "A" + tr + "," + tr + " 0 1,0 " + (tw/2 + 0.1) + "," + (th/2 - tr) + "z";
var path = outerpath + innerpath;
var mask = paper.path(path).attr({'stroke': 0, 'fill' : '#ccc', 'fill-opacity' : 0.9});
innerpath
来创建另一个形状并使用另一种颜色填充它。太神奇了。