JS?簡單實(shí)現(xiàn)拖拽評(píng)星的示例代碼
廢話開篇:通過 canvas 簡單拖拽評(píng)星,主要是通過個(gè)人的理解去實(shí)現(xiàn)這樣的一個(gè)效果。
一、實(shí)現(xiàn)效果
html
<div class="main"> <div class="score_container"> <canvas id="canvas" height="100"></canvas> <div id="score" class="score">評(píng)分:0</div> </div> </div>
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
// 星星數(shù)據(jù)對象 ? ? 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}){ ? ? ? ? ? ? // 它對應(yīng)的整數(shù)分?jǐn)?shù) ? ? ? ? ? ? this.score = currentPentagramIndex + 1 ? ? ? ? ? ? // 工具函數(shù) ? ? ? ? ? ? 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) { ? ? ? ? ? ? ? ? ? ? // 最右側(cè)的點(diǎn) ? ? ? ? ? ? ? ? ? ? this.minX = point[0] ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if(index == 3) { ? ? ? ? ? ? ? ? ? ? // 最左側(cè)的點(diǎn) ? ? ? ? ? ? ? ? ? ? this.maxX = point[0] ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }) ? ? ? ? } ? ? } ? ? // 星星管理器 ? ? class PentagramManage{ ? ? ? ? canvas = null//畫板相關(guān) ? ? ? ? context = null ? ? ? ? pentagramNum = 1//星星個(gè)數(shù) ? ? ? ? isMouseDown = false//鼠標(biāo)是否按下 ? ? ? ? progress = 0//當(dāng)前評(píng)分位置 ? ? ? ? pentagramRadius = 15//星星半徑 ? ? ? ? pentagramSep = 10//星星間間隔 ? ? ? ? pentagrams = []//記錄每一個(gè)星星對象 ? ? ? ? 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)') ? ? ? ? ? ? }) ? ? ? ? } ? ? ? ? // 綁定鼠標(biāo)事件 ? ? ? ? bindMouseEvent(){ ? ? ? ? ? ? document.onmousemove = (event)=>{ ? ? ? ? ? ? ? ? if(this.isMouseDown){ ? ? ? ? ? ? ? ? ? ? let { left } = this.getElementPosition(document.getElementById('canvas')) ? ? ? ? ? ? ? ? ? ? this.progress = event.clientX - left ? ? ? ? ? ? ? ? ? ? this.draw() ? ? ? ? ? ? ? ? ? ? this.getCurrentScore() ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? //鼠標(biāo)按下事件 ? ? ? ? ? ? document.onmousedown = (event)=>{ ? ? ? ? ? ? ? ? this.isMouseDown = true ? ? ? ? ? ?? ? ? ? ? ? ? ? ? let { left } = this.getElementPosition(document.getElementById('canvas')) ? ? ? ? ? ? ? ? ? ? this.progress = event.clientX - left ? ? ? ? ? ? ? ? ? ? this.draw() ? ? ? ? ? ? ? ? ? ? this.getCurrentScore() ? ? ? ? ? ? } ? ? ? ? ? ? //鼠標(biāo)抬起事件 ? ? ? ? ? ? document.onmouseup = ()=>{ ? ? ? ? ? ? ? ? this.isMouseDown = false ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? // 計(jì)算分?jǐn)?shù) ? ? ? ? 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 = "評(píng)分:" + score ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? document.getElementById('score').innerHTML = "評(píng)分:" + 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)
二、總結(jié)與思考
上層無鏤空
上層有鏤空
通過 canvas 實(shí)現(xiàn)一層鏤空五角星層,再在底層添加一個(gè)進(jìn)度層,這樣在拖動(dòng)的時(shí)候就能通過拖拽的位置進(jìn)行數(shù)據(jù)處理,從而計(jì)算出星級(jí)數(shù)。代碼拙劣,大神勿笑
到此這篇關(guān)于JS 簡單實(shí)現(xiàn)拖拽評(píng)星的示例代碼的文章就介紹到這了,更多相關(guān)JS拖拽評(píng)星內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS實(shí)現(xiàn)運(yùn)動(dòng)緩沖效果的封裝函數(shù)示例
這篇文章主要介紹了JS實(shí)現(xiàn)運(yùn)動(dòng)緩沖效果的封裝函數(shù),涉及JavaScript時(shí)間函數(shù)與數(shù)值運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2018-02-02如何消除inline-block屬性帶來的標(biāo)簽間間隙
這篇文章主要介紹了如何消除inline-block屬性帶來的標(biāo)簽間間隙的相關(guān)資料,需要的朋友可以參考下2016-03-03webpack打包node.js后端項(xiàng)目的方法
本篇文章主要介紹了webpack打包node.js后端項(xiàng)目的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03js實(shí)現(xiàn)iframe自動(dòng)自適應(yīng)高度的方法
這篇文章主要介紹了js實(shí)現(xiàn)iframe自動(dòng)自適應(yīng)高度的方法,涉及javascript操作iframe框架的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-02-02JavaScript基礎(chǔ)知識(shí)之方法匯總結(jié)
本文給大家分享了javascript基礎(chǔ)知識(shí),包括數(shù)組的方法,函數(shù)的方法,數(shù)字的方法,對象的方法,字符串的方法,常規(guī)方法,正則表達(dá)式方法,本文介紹的非常詳細(xì),具有參考價(jià)值特此分享供大家參考2016-01-01性能優(yōu)化篇之Webpack構(gòu)建速度優(yōu)化的建議
這篇文章主要介紹了性能優(yōu)化篇之Webpack構(gòu)建速度優(yōu)化的建議,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04js如何實(shí)現(xiàn)設(shè)計(jì)模式中的模板方法
都知道在js中如果定義兩個(gè)相同名稱的方法,前一個(gè)方法就會(huì)被后一個(gè)方法覆蓋掉,使用此特點(diǎn)就可以實(shí)現(xiàn)模板方法,感興趣的朋友可以了解下本文哈2013-07-07