时钟
canvas绘制时钟
<canvas id="canvas" width="600" height="600"></canvas> <script> var canvasId=document.getElementById("canvas"); var ctx=canvasId.getContext("2d"); setInterval(()=>{ ctx.save() ctx.clearRect(0, 0, 600, 600) ctx.translate(300, 300) // 设置中心点,此时300,300变成了坐标的0,0 ctx.save() //大 ctx.beginPath(); ctx.arc(0,0,100,0,2 * Math.PI); ctx.stroke(); ctx.closePath(); //小 ctx.beginPath(); ctx.arc(0,0,5,0,2 * Math.PI); ctx.stroke(); ctx.closePath(); //当前时间 var time = new Date(); let hour = time.getHours() % 12; let min = time.getMinutes(); let sec = time.getSeconds(); console.log("ss",hour,min,sec); //时钟 ctx.rotate(2 * Math.PI /12 *hour + 2*Math.PI/12 *(min/60) -Math.PI /2); ctx.beginPath() //moveTo设置画线起点 ctx.moveTo(-10,0) //lineTo设置画线经过点 ctx.lineTo(54,0); ctx.lineWidth=6; ctx.strokeStyle = '#000' ctx.stroke() ctx.closePath() // 恢复成上一次save的状态 ctx.restore() // 恢复完再保存一次 ctx.save() //分钟 ctx.rotate(2* Math.PI/60 * min + 2* Math.PI/60 *(sec/60) - Math.PI/2); ctx.beginPath(); ctx.moveTo(-10, 0); ctx.lineTo(90, 0); ctx.lineWidth=3; ctx.strokeStyle = '#000' ctx.stroke() ctx.closePath() ctx.restore() ctx.save() //秒针 ctx.rotate(2 * Math.PI / 60 * sec - Math.PI / 2) ctx.beginPath() ctx.moveTo(-10, 0) ctx.lineTo(80, 0) ctx.strokeStyle = '#666' ctx.stroke() ctx.closePath() ctx.restore() ctx.save() // 绘制刻度,也是跟绘制时分秒针一样,只不过刻度是死的 ctx.lineWidth = 1 for (let i = 0; i < 60; i++) { ctx.rotate(2 * Math.PI / 60) ctx.beginPath() ctx.moveTo(90, 0) ctx.lineTo(100, 0) // ctx.strokeStyle = 'red' ctx.stroke() ctx.closePath() } ctx.restore() ctx.save() ctx.lineWidth = 5 for (let i = 0; i < 12; i++) { ctx.rotate(2 * Math.PI / 12) ctx.beginPath() ctx.moveTo(85, 0) ctx.lineTo(100, 0) ctx.stroke() ctx.closePath() } ctx.restore() ctx.restore() },1000) </script>
2刮刮卡
html <div class="html5"> <div class="warp"> <div class="inner-warp"> <canvas id="canvas" class="canvas"></canvas> <div class="rs mentos abs"></div> <div class="rs empty abs"></div> </div> </div> </div>
css <style> * { margin: 0; padding: 0; } html, body { height: 100%; overflow: hidden; } .html5{ 320px; height: 188px; background: url(http://img.aimoge.com/Fnna0oYkHLIJqoqJ5L10aJwS7-99) 0 0 no-repeat; background-size: 100% auto; margin:0 auto; position: relative; } .abs { position: absolute; } .warp{ position: relative; 260px; height: 120px; top: 31px; left: 30px; padding:6px 10px; box-sizing: border-box; background-color: #fff; } .inner-warp{ 100%; height:100%; position: relative; } .canvas { position:absolute; top: 0px; left: 0px; z-index: 350; } .html5 .rs { position: absolute; 240px; height: 108px; top: 0px; left: 0px; display: none; background-size: 100% auto; background-repeat: no-repeat; z-index: 300; } .html5 .rs.mentos { background-image:刮刮卡下面的图片; }
<script> var img = new Image(); img.crossOrigin = ''; img.src = 'http://img.aimoge.com/FluRH5rP3ur-Se2XTKatZaLZvdTD'; function initCanvasResult(){ document.querySelector(".mentos").style.display="block"; } //计算偏移量 function getPoint(obj){ let t = obj.offsetTop; let l = obj.offsetLeft; while(obj = obj.offsetParent){ t += obj.offsetTop; l += obj.offsetLeft; } return{ offsetTop:t, offsetLeft:l } } function getTransparentPercent(ctx,width,height){ console.log("ss",ctx,width,height) var imgData = ctx.getImageData(0, 0, width, height), pixles = imgData.data, transPixs = []; console.log("sssss",imgData,pixles,transPixs) for (var i = 0, j = pixles.length; i < j; i += 4) { var a = pixles[i + 3]; if (a < 128) { transPixs.push(i); } } return (transPixs.length / (pixles.length / 4) * 100).toFixed(2); } img.onload =function(){ const canvas = document.querySelector('#canvas'); let canvasOffset = getPoint(canvas); let ctx = canvas.getContext('2d'); let width=240,height=108,precent=0; canvas.width = width; canvas.height = height; //偏移量 let offsetX = canvasOffset.offsetLeft, offsetY = canvasOffset.offsetTop; ctx.drawImage(img, 0, 0, width, height); //显示挂挂卡下面的底图 initCanvasResult(); var mousedown = false; canvas.addEventListener('touchstart',function(e){ mousedown = true; ctx.globalCompositeOperation = "destination-out"; ctx.lineWidth = 40; ctx.lineCap = "round"; ctx.lineJoin = "round"; }) canvas.addEventListener('touchmove',function(e){ e.preventDefault(); let touches = e.changedTouches[0]; if(!mousedown){ return; } if(touches){ var x = touches.clientX - offsetX, y = touches.clientY - offsetY; ctx.arc(x, y, 10, 0, Math.PI * 2); ctx.fill(); } }) canvas.addEventListener('touchend',function(e){ mousedown=false; precent = getTransparentPercent(ctx,width,height); if (precent > 50 && precent != 100) { ctx.clearRect(0, 0, width, height); alert('恭喜,获得礼品一份!!!'); } }) } </script>
圆环,只写个大概,等有时间加入到组件库里面去
//html <div class="pie-wrap pie-wrap-small"> <canvas id="pie-canvas" class="pie-canvas"></canvas> <div class="pie-text-wrap"> <div class="title"> 25% </div> </div> </div> //css .pie-wrap{ position: relative; } .pie-wrap-small{ 110px; height: 110px; } .pie-canvas{ 110px; height: 110px; } .pie-text-wrap{ position: absolute; top: 0px; left: 0px; 110px; height: 110px; display: flex; flex-direction: column; justify-content: center; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .pie-text-wrap .title{ font-weight: bold; font-size: 26px; letter-spacing: 0; text-align: center; line-height: 30px; } //js var setProps={ type: 'info', size: 'small', value: '0.25', title: '', subtitle: '', titleColor: '', subtitleColor: '#666', /*背景色*/ bgRingColor: "#eee", /** 上层圆环颜色 */ fgRingColor: '#3377FF' } function calcSizes(){ /** 视觉稿中饼图边长 */ let canvasCSSEdgeLength = 110 /** 视觉稿中线段宽度 */ let lineCSSWidth = 10 switch (setProps.size) { case 'small': canvasCSSEdgeLength = 110 lineCSSWidth = 10 break case 'large': canvasCSSEdgeLength = 220 lineCSSWidth = 20 break } const pixelRatio = 750 / Math.min(document.documentElement.clientWidth, 750); /** canvas 实际边长 */ /** canvas 实际边长 */ const canvasEdgeLength =(canvasCSSEdgeLength * window.devicePixelRatio) / pixelRatio; /** canvas 中线段实际宽度 */ const lineWidth = (lineCSSWidth * window.devicePixelRatio) / pixelRatio console.log("qqq",canvasEdgeLength,lineWidth); return{ canvasEdgeLength, lineWidth } } function initRenderCanvas(){ const canvas=document.getElementById("pie-canvas"); const ctx = canvas.getContext("2d"); //圆心x轴 let canvasEdgeLength=calcSizes().canvasEdgeLength; let lineWidth =calcSizes().lineWidth; canvas.width=canvasEdgeLength; canvas.height=canvasEdgeLength; const centerX = canvasEdgeLength/2; const centerY = centerX; let percentValue = setProps.value; console.log("sss",centerX) //圆环半径 const ringRadius = centerX - lineWidth /2; /** 圆弧的起点,x轴方向开始计算,单位以弧度表示 */ const startAngle = -0.5 * Math.PI /** 下层圆环的终点 */ const bgRingEndAngle = 1.5 * Math.PI /** 上层圆环的终点,根据百分比计算 */ const fgRingAngle = (2 * setProps.value - 0.5) * Math.PI ctx.lineWidth = lineWidth // 线段宽度 ctx.lineCap = 'round' // 线段末端样式 //绘制下层灰色圆环 ctx.beginPath() ctx.strokeStyle = setProps.bgRingColor // 画笔颜色 ctx.arc(centerX, centerY, ringRadius, startAngle, bgRingEndAngle, false) ctx.stroke() // 绘制上层百分比圆环 if(percentValue>0){ ctx.beginPath(); ctx.strokeStyle = setProps.fgRingColor ctx.arc(centerX, centerY, ringRadius, startAngle, fgRingAngle, false) ctx.stroke(); } } window.onload=function(){ calcSizes() initRenderCanvas(); }
上面这个圆环可以继续拓展
setProps这个对象里面定义的属性可以继续加进去封装成组件,知道就行,懒得弄
参考地址:https://juejin.cn/post/6986785259966857247