1.效果如下
画单个爱心的效果如下:
2.HTML,CSS代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
<script type="text/javascript" src="https://cdn.staticfile/jquery/1.10.2/jquery.min.js"></script>
</head>
<style type="text/css" media="screen">
html,body,canvas{
padding: 0;
margin: 0;
display: block;
}
</style>
<body>
<canvas id="heart">
</canvas>
</body>
</html>
3.JS代码
首先单个爱心主要的思路是把爱心曲线分割成一个一个的点,然后利用直线把每一个点连接起来。这里我们需要知道的是爱心曲线的x,y方程 爱心方程 ,这个网站给出一些曲线的x,y表达式。
满屏幕的爱心就是把单个爱心重复画。
两个类
function Point(x,y){
this.x = x
this.y = y
this.scale = Math.random()*rand(1,3)
}
Point.prototype={
mul:function(){
this.x *= this.scale
this.y *= this.scale
}
}
function rand(min,max){
return ~~(Math.random()*(max-min+1)+min)
}
function Position (cw,ch,x,y){
this.cw=cw
this.ch=ch
this.offSetx = x||0
this.offSety = y||0
this.init()
}
Position.prototype={
init:function(){
if(this.offSetx ==0 && this.offSety== 0){
this.offSetx = rand(20,this.cw-20)
this.offSety = rand(20,this.ch-20)
}
}
}
function Heart (ctx,p) {
this.points = []
this.length = 0
this.ctx = ctx
this.position = p
this.scale = (Math.random()+0.3)*rand(1,1.6)
this.lightness = rand(30,80)
this.init()
// x = 16 sin^3 t
// y = 13 cos t - 5 cos 2t - 2 cos 3t - cos 4t
// http://www.wolframalpha/input/?i=x+%3D+16+sin%5E3+t%2C+y+%3D+(13+cos+t+-+5+cos+2t+-+2+cos+3t+-+cos+4t)
}
Heart.prototype = {
init:function(){
for (let i = 0; i < 2*Math.PI; i += 2*Math.PI/30) {
let x = 16 * Math.pow(Math.sin(i), 3);
let y = 13 * Math.cos(i) - 5 * Math.cos(2 * i) - 2 * Math.cos(3 * i) - Math.cos(4 * i);
this.points.push(new Point(x, y));
}
this.length = this.points.length;
},
get: function(i) {
return this.points[i];
},
draw:function(){
this.ctx.save()
this.ctx.beginPath()
this.ctx.translate(this.position.offSetx,this.position.offSety)
this.ctx.fillStyle = 'hsla(0 ,100%,'+this.lightness+'%,0.6)'
this.ctx.lineWidtn = 2
this.ctx.lineCap = 'round'
this.ctx.scale(this.scale,this.scale)
this.ctx.moveTo(this.get(0).x,-this.get(0).y)
for(let i = 1 ;i < this.length ; i++){
this.ctx.lineTo(this.get(i).x,-this.get(i).y)
}
this.ctx.closePath()
this.ctx.fill()
this.ctx.restore()
}
}
function Canvas(ctx,cw,ch){
this.heartNum = 66
this.hearts=[]
this.length = 0
this.cw = cw
this.ch = ch
this.ctx = ctx
this.init()
}
Canvas.prototype={
init:function(){
while(this.heartNum--){
let p = new Position(this.cw,this.ch)
this.hearts.push(new Heart(this.ctx,p))
}
this.length = this.hearts.length
},
drawHearts:function(){
let i = this.length
while(i--){
this.hearts[i].draw()
}
}
}
定义了四个类:
Point
用来保存点的坐标
Position
用来保存每一个爱心的偏移量,这些偏移量在后来做随机分布爱心的时候会用到
Heart
传入两个参数分别是,ctx:canvas的2d画布对象,Position对象p,里面包含有offSetx:x偏移量,offSety:y偏移量。
this.ctx.translate(this.position.offSetx,this.position.offSety)
意思是重新定义画布的基准点,定位到 (offSetx,offSety),这个点的在后面的设置中就是(0,0),在设置基准点的时候注意要用到this.ctx.save() this.ctx.restore()
,因为基准点改变了,save是保存原来画布的设置,restore是还原原来画布的设置。
Canvas
整个画布对象,用来规定有多少爱心。
初始化以及执行
$(function(){
let c = document.getElementById('heart')
let cw = c.width = $(window).width()
let ch = c.height = $(window).height()
let ctx = c.getContext('2d')
let canvas = new Canvas(ctx,cw,ch)
canvas.drawHearts()
})
4.说明
我想把每个爱心的大小也随机一下,this.ctx.scale这个方法一定要放在绘制的前面
this.ctx.scale(this.scale,this.scale)
this.ctx.moveTo(this.get(0).x,-this.get(0).y)
for(let i = 1 ;i < this.length ; i++){
this.ctx.lineTo(this.get(i).x,-this.get(i).y)
}
this.ctx.closePath()
}
更多推荐
javascript中canvas画爱心
发布评论