js五星好评组价开发

五星好评

产品需求

1.三组数据并行排列,鼠标放在文字上时后面的星星样式不变。
2.鼠标滑过,指针之前的星星变成红色的,鼠标离开,全部变成原样。
3.点击过后,鼠标离开星星,点击位置前的星星固定是红色的,鼠标再次滑过,点击位置之前的星星不影响,之后的星星随鼠标的滑过变成红色
4.鼠标滑过或点击,会有不同等级表情显示在星星的上方,鼠标离开,表情消失。

效果图:

默认样式

鼠标滑过 和 离开


鼠标点击和离开

星星和表情图片提供


分析
  • 点击后,要把点击的数据发送出去,抛发事件
  • 表情的移动位置是点击星星的位置
  • 每组的星星小于等于滑过坐标,则为红色,每组的星星大于点击位置的则为原样(无色)
  • 点击之后,小于点击位置的,是红色,否则是原样

js代码,封装组件

import Utils from "./Utils.js";
export default class FaceStar extends EventTarget{
    label;
    list=[];   // 把创建的星星存储到数组中,查找点击时的坐标用到
    pos=-1;    //和点击时的坐标进行比较
    constructor(_label){
        super();
        this.label=_label;
        this.elem=this.createElem();
    }
    createElem(){
        if(this.elem) return this.elem;
        let div=Utils.ce("div",{
            height:"32px",
            float:"left",    //一共三组,并行排列,所以要浮动
            marginRight:"20px",
            position:"relative"
        });
        let span=Utils.ce("span",{   //文字容器
            marginRight:"10px",
            position:"relative",
            top:"-3px"
        });
        span.textContent=this.label;
        let con=Utils.ce("ul",{   //  星星容器
            listStyle:"none",
            margin:0,
            padding:0,
            height:"32px",
            position:"relative",
            display:"inline-block"  //设置成行内块元素,可以和文本并行排列
        })
        for(var i=0;i<5;i++){   //创建星星
            let star=Utils.ce("li",{
                width:"16px",
                height:"16px",
                float:"left",
                marginTop:"16px",
                backgroundImage:"url(./img/commstar.png)"
            });
            this.list.push(star);  //存储到数组
            con.appendChild(star)
        }
       this.face=Utils.ce("div",{  //创建表情容器    块级元素上下排列
            width:"16px",
            height:"16px",
            position:"absolute",
            backgroundPositionX:-20*4+"px",
            display:"none",
            backgroundImage:"url(./img/face-red.png)"
        })
        con.appendChild(this.face);
        div.appendChild(span);
        div.appendChild(con);
        con.addEventListener("mouseover",e=>this.mouseHandler(e)) //事件委托,用mouseover有冒泡触发
        con.addEventListener("mouseleave",e=>this.mouseleaveHandler(e))  //离开时针对ul,不需要冒泡
        con.addEventListener("click",e=>this.mouseHandler(e))
        return div;
    }
    appendTo(parent){
        if(typeof parent==="string") parent=document.querySelector(parent);
        parent.appendChild(this.elem);
    }
    mouseHandler(e){
        if(e.target.constructor!==HTMLLIElement) return;
        var index=this.list.indexOf(e.target);  //鼠标滑过星星时的坐标
        if(e.type==="mouseover"){
            this.face.style.display="block";
            this.face.style.backgroundPositionX=(4-index)*-20+"px"
            this.face.style.left=e.target.offsetLeft+'px';  //用星星的位置来让表情跟随移动
            this.list.forEach((item,i)=>{
                if(i<=index){
                    item.style.backgroundPositionY="-16px"
                }else if(i>this.pos){   //小于点击时的位置不执行,则固定住了点击的位置

                    item.style.backgroundPositionY="0px"
                }
            })
        }else if(e.type==="click"){
            this.pos=index;  //this.pos 是点击时候的位置
            this.setStar(this.pos);
            var evt=new Event("change");
            evt.pos=this.pos;
            this.dispatchEvent(evt);
        }
    }
    mouseleaveHandler(e){
        this.face.style.display="none";
       this.setStar(this.pos)
    }
    setStar(index){         //点击位置之后的都是无色星星   可以点击小于固定位置的星星
        this.list.forEach((item,i)=>{
            if(i<=index){
                item.style.backgroundPositionY="-16px"
            }else{
                item.style.backgroundPositionY="0px"
            }
        })
    }
}

html页面,传递数据,接收FaceStar.js中传出来的数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script type="module">
      import FaceStar from "./js/FaceStar.js";
        let arr=["快速包装","快递服务","送货上门"]
        arr.forEach(item=>{
            let face=new FaceStar(item);
            face.appendTo("body");
            face.addEventListener("change",changeHandler);
        })

        function changeHandler(e){
            console.log(e.pos,this.label);
        }
     
    </script>
</body>
</html>

Utils.js是工具包

export default class Utils{
   static time=0;
   static ids=0;
   static timeManage={};
   //代码性能
   static timeStart(){
        if(Utils.time) return;
        Utils.time=new Date().getTime();
    }
   static timeEnd(){
        var t=new Date().getTime()-Utils.time;
        Utils.time=0;
        return t;
    }
    static ts(){
        Utils.ids++;
        Utils.timeManage[Utils.ids]=new Date().getTime();
        return ids;
    }
    static te(id){
        if(!Utils.timeManage[Utils.id]) return 0;
        var t=new Date().getTime()-Utils.timeManage[Utils.id];
        delete Utils.timeManage[Utils.id];
        return t;
    }
    //随机颜色
    static randomColor(){
        var col="#";
        for(var i=0;i<6;i++){
            col+=Math.floor(Math.random()*16).toString(16);
        }
        return col;
    }
    //随机数值
    static random(min,max){
        return Math.floor(Math.random()*(max-min)+min);
    }
    //创建元素  设置样式  插入父级元素
     static ce(type,style,parent){
        var elem=document.createElement(type);
        if(style){
            for(var prop in style){
                elem.style[prop]=style[prop];
            }
        }
        if(typeof parent==="string") parent=document.querySelector(parent);
        if(parent) parent.appendChild(elem);
        return elem;
    }
    //读取css样式
    static setStyle(styles){
        var style=document.createElement("style");
        document.head.appendChild(style);
        var styleSheet=document.styleSheets[document.styleSheets.length-1];
        for(var prop in styles){
            Utils.addCss(styleSheet,prop,styles[prop]);
        }
    }
    //添加css样式
    static addCss(styleSheet,selector,style){
        var str=selector+" {";
        for(var prop in style){
            var value=style[prop]
            prop=prop.replace(/([A-Z])/g,function($1){
                return "-"+$1.toLowerCase();
            })
            str+=prop+":"+value+";"
        }
        str+=" }";
        styleSheet.insertRule(str,styleSheet.cssRules.length);
    }
    //css样式转化为js内样式
    static CSStoString(str){
       return str.replace(/(?<=:)(.*?)(?=;)|-[a-z](?=.+:)|;/g,function(item){
            if(item===";") return ","
            if(item[0]==="-")  return item[1].toUpperCase();
            return "'"+item.trim()+"'";
        });
    }
    //字符串css转换为js内样式
    static CSStoObject(str){
        str=Utils.CSStoString(str);
       return  str.split(",").reduce((value,item)=>{
           item=item.replace(/\n/g,"");
            var arr=item.split(":");
            arr[0]=arr[0].replace(/\s/g,"");
            if(arr[1]===undefined) return value;
            arr[1]=arr[1].replace(/'/g,"");
            value[arr[0]]=arr[1];
            return value;
        },{})
    }
}

猜你喜欢

转载自www.cnblogs.com/94-Lucky/p/13405918.html