目录
废话开篇:通过 canvas 简单拖拽评星,主要是通过个人的理解去实现这样的一个效果。
一、实现效果
html
评分:0
css
.main { display: flex; flex-direction: row; justify-content: start; align-items: flex-start; padding-top: 20px; padding-left: 20px; } .score_container { display: flex; flex-direction: column; justify-content: center; align-items: center; padding-top: 20px; } .score { margin-top: 20px; }
js
// 星星数据对象 class pentagram{ points = [] minx = 0 maxx = 0 deg = (math.pi / 180) score = 0 constructor(index,r,center){ this.savepentagramdata(index,r,center) } // 绘制星星 savepentagramdata(currentpentagramindex,r,{x,y}){ // 它对应的整数分数 this.score = currentpentagramindex 1 // 工具函数 let cos = (d)=>{ return math.cos(d * this.deg) } let sin = (d)=>{ return math.sin(d * this.deg) } let tan = (d)=>{ return math.tan(d * this.deg) } let square = (num)=> { return math.pow(num,2) } // 外边比例 let t = 1 / ((1 square(tan(18))) / (3 - square(tan(18)))) this.points = [ [0,1], [t*cos(54),t*sin(54)], [cos(18),sin(18)], [t*cos(18),-t*sin(18)], [cos(54),-sin(54)], [0,-t], [-cos(54),-sin(54)], [-t*cos(18),-t*sin(18)], [-cos(18),sin(18)], [-t*cos(54),t*sin(54)], [0,1], ] this.points.foreach((point,index)=>{ point[0] = x point[0] * (r / t) point[1] = y point[1] * (r / t) if(index == 7) { // 最右侧的点 this.minx = point[0] } if(index == 3) { // 最左侧的点 this.maxx = point[0] } }) } } // 星星管理器 class pentagrammanage{ canvas = null//画板相关 context = null pentagramnum = 1//星星个数 ismousedown = false//鼠标是否按下 progress = 0//当前评分位置 pentagramradius = 15//星星半径 pentagramsep = 10//星星间间隔 pentagrams = []//记录每一个星星对象 constructor(pentagramnum){ this.pentagramnum = pentagramnum this.initdata() this.draw() this.bindmouseevent() } // 初始化 initdata(){ this.canvas = document.getelementbyid('canvas') for(let i = 0;i < this.pentagramnum;i ){ let pentagram = new pentagram(i,this.pentagramradius,{x:35 i * (this.pentagramradius * 2 this.pentagramsep),y:(this.canvas.height / 2.0) }) this.pentagrams.push(pentagram) if(i == this.pentagramnum - 1){ this.canvas.width = pentagram.maxx 20 } } this.context = this.canvas.getcontext('2d'); this.context.fillstyle='white'; } //绘制 draw(){ this.context.clearrect(0,0,this.canvas.width,this.canvas.height); this.drawbottomplate() let hook = ()=>{ this.pentagrams.foreach((pentagramitem)=>{ this.drawpentagram(pentagramitem) }) } this.drawhollowout(hook) this.drawstrokehollowout(hook) } // 绘制底色 drawbottomplate(){ this.context.save() this.context.fillstyle= 'rgb(247,190,80)'; this.context.beginpath(); this.context.rect(0, 0, this.progress, this.canvas.height); this.context.closepath(); this.context.fill(); this.context.restore() } // 绘制镂空五角星 drawhollowout(hook){ this.context.beginpath(); this.context.rect(0, 0, this.canvas.width, this.canvas.height); hook() this.context.closepath(); this.context.fill(); } // 绘制五星边框 drawstrokehollowout(hook){ this.context.save(); this.context.strokestyle = 'rgb(247,190,80)'; // this.context.stroke.width = 1 this.context.beginpath(); this.context.rect(0, 0, this.canvas.width, this.canvas.height); hook() this.context.closepath(); this.context.stroke(); this.context.restore(); } // 绘制星星 drawpentagram(pentagramitem){ pentagramitem.points.foreach((point,index)=>{ eval('this.context.' (index == 0 ? 'moveto(' : 'lineto(') '...point)') }) } // 绑定鼠标事件 bindmouseevent(){ document.onmousemove = (event)=>{ if(this.ismousedown){ let { left } = this.getelementposition(document.getelementbyid('canvas')) this.progress = event.clientx - left this.draw() this.getcurrentscore() } } //鼠标按下事件 document.onmousedown = (event)=>{ this.ismousedown = true let { left } = this.getelementposition(document.getelementbyid('canvas')) this.progress = event.clientx - left this.draw() this.getcurrentscore() } //鼠标抬起事件 document.onmouseup = ()=>{ this.ismousedown = false } } // 计算分数 getcurrentscore(){ let score = 0 let firstpentagram = this.pentagrams.find((pentagram)=>{ return this.progress <= pentagram.maxx }) if(firstpentagram){ let float = (math.floor(((this.progress - firstpentagram.minx) / (firstpentagram.maxx - firstpentagram.minx)) * 10)) / 10 float = float > 0 ? float : 0 score = (firstpentagram.score - 1) float document.getelementbyid('score').innerhtml = "评分:" score } else { document.getelementbyid('score').innerhtml = "评分:" this.pentagrams.length } } // dom在浏览器的位置 getelementposition(element){ let top = element.offsettop let left = element.offsetleft let width = element.offsetwidth let height = element.offsetheight var currentparent = element.offsetparent; while (currentparent !== null) { top = currentparent.offsettop left = currentparent.offsetleft currentparent = currentparent.offsetparent } return {top,left,width,height} } } var pentagram = new pentagrammanage(4)
二、总结与思考
上层无镂空
上层有镂空
通过 canvas 实现一层镂空五角星层,再在底层添加一个进度层,这样在拖动的时候就能通过拖拽的位置进行数据处理,从而计算出星级数。代码拙劣,大神勿笑