时钟

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{
width: 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;
width: 260px;
height: 120px;
top: 31px;
left: 30px;
padding:6px 10px;
box-sizing: border-box;
background-color: #fff;
}
.inner-warp{
width:100%;
height:100%;
position: relative;
}
.canvas {
position:absolute;
top: 0px;
left: 0px;
z-index: 350;
}
.html5 .rs {
position: absolute;
width: 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{
width:110px;
height: 110px;
}
.pie-canvas{
width: 110px;
height: 110px;
}
.pie-text-wrap{
position: absolute;
top: 0px;
left: 0px;
width: 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
日常所遇,随手而记。
浙公网安备 33010602011771号