JS 简单实现拖拽评星的示例代码

 更新时间:2023年05月06日 08:28:21   作者:头疼脑胀的代码搬运工  
本文主要介绍了JS 简单实现拖拽评星,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

废话开篇:通过 canvas 简单拖拽评星,主要是通过个人的理解去实现这样的一个效果。

一、实现效果

html

<div class="main">
        <div class="score_container">
          <canvas id="canvas" height="100"></canvas>
          <div id="score" class="score">评分: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

// 星星数据对象
    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 实现一层镂空五角星层,再在底层添加一个进度层,这样在拖动的时候就能通过拖拽的位置进行数据处理,从而计算出星级数。代码拙劣,大神勿笑 

到此这篇关于JS 简单实现拖拽评星的示例代码的文章就介绍到这了,更多相关JS拖拽评星内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • JS中图片压缩的方法小结

    JS中图片压缩的方法小结

    这篇文章主要介绍了JS中图片压缩的方法,包括等比压缩图片的方法,需要的朋友可以参考下
    2017-11-11
  • JS实现运动缓冲效果的封装函数示例

    JS实现运动缓冲效果的封装函数示例

    这篇文章主要介绍了JS实现运动缓冲效果的封装函数,涉及JavaScript时间函数与数值运算相关操作技巧,需要的朋友可以参考下
    2018-02-02
  • ES6中Proxy代理用法实例浅析

    ES6中Proxy代理用法实例浅析

    这篇文章主要介绍了ES6中Proxy代理用法,结合实例形式简单分析了Proxy代理的概念、功能、使用方法与相关注意事项,需要的朋友可以参考下
    2017-04-04
  • 如何消除inline-block属性带来的标签间间隙

    如何消除inline-block属性带来的标签间间隙

    这篇文章主要介绍了如何消除inline-block属性带来的标签间间隙的相关资料,需要的朋友可以参考下
    2016-03-03
  • webpack打包node.js后端项目的方法

    webpack打包node.js后端项目的方法

    本篇文章主要介绍了webpack打包node.js后端项目的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • Layui实现带查询条件的分页

    Layui实现带查询条件的分页

    这篇文章主要为大家详细介绍了Layui实现带查询条件的分页,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • js实现iframe自动自适应高度的方法

    js实现iframe自动自适应高度的方法

    这篇文章主要介绍了js实现iframe自动自适应高度的方法,涉及javascript操作iframe框架的技巧,非常具有实用价值,需要的朋友可以参考下
    2015-02-02
  • JavaScript基础知识之方法汇总结

    JavaScript基础知识之方法汇总结

    本文给大家分享了javascript基础知识,包括数组的方法,函数的方法,数字的方法,对象的方法,字符串的方法,常规方法,正则表达式方法,本文介绍的非常详细,具有参考价值特此分享供大家参考
    2016-01-01
  • 性能优化篇之Webpack构建速度优化的建议

    性能优化篇之Webpack构建速度优化的建议

    这篇文章主要介绍了性能优化篇之Webpack构建速度优化的建议,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • js如何实现设计模式中的模板方法

    js如何实现设计模式中的模板方法

    都知道在js中如果定义两个相同名称的方法,前一个方法就会被后一个方法覆盖掉,使用此特点就可以实现模板方法,感兴趣的朋友可以了解下本文哈
    2013-07-07

最新评论