canvas实现你画我猜(入门级别)
初学canvas做的一个小功能,大佬勿喷
之前一直没有去了解canvas 最近玩steam你画我猜感觉很有意思 就打算自己实现一个单机版的
成果图:
预备工作: vs code,及几张图片
因为考虑到体积问题没有用上jquery 先说一下这次使用到的基本的几个canvas方法
moveTo绘制心线条起点
lineTo绘制线条的末尾
stroke绘制线条结束
clearRect 清除一个正方形出来
fillRect 填充一个正方形
beginPath 重新绘制一条新的线条
beginPath这个方法比较关键 同一条线条的情况下换颜色,所有线条都变颜色了,回放自己画图时候也会出问题
canvas中文文档:www.canvasapi.cn/CanvasRende…
Hmtl部分
<img src="./huabu.jpg" id="scream" class="img" >
<canvas class="canvas" id="canvas" width="800" height="800"></canvas>
</div>
<div class="function">
<div></div>
<div>
<button onclick="start()">清除绘制</button>
</div>
<div>
<button onclick="reset()">回放绘制</button>
</div>
<div>
<input type="radio" name="mode" id="canvasMode" onChange="modeChange(1)"> <label for="canvasMode">画布模式</label>
<input type="radio" name="mode" id="backgroundMode" onChange="modeChange(2)"> <label for="backgroundMode">背景颜色模式</label>
</div>
<div class="button">
<input type="color" id="color"> 背景颜色
</div>
<div class="button">
<input type="color" id="fontColor"> 画笔颜色
</div>
<div class="button lineWidth">
<input type="range" value="1" min="1" id="fontWidth"><span style="margin-left:12px;width:95px">画笔粗细:</span>
<div class="widthPercentage" id="percentage">
</div>
<div class="button">
<span id="lineNum">1</span>
</div>
</div>
<div class="button lineWidth">
<input type="range" value="15" min="1" id="rubberWidth"><span style="margin-left:12px;width:95px">橡皮大小:</span>
<div class="button">
<span id="rubberNum">15</span>
</div>
</div>
<div>
<button onclick="eraserClick()" id='eraser'>橡皮擦 </button>
</div>
</div>
</div>
css部分
body {
margin: 0;
}
.canvasBox {
display: flex;
}
button,.button {
margin: 12px;
}
.function {
margin: auto 0;
}
.lineWidth {
position: relative;
display: flex;
align-items: center;
}
.widthPercentage{
position: absolute;
top: 34px;
left: 30%;
height: 20px;
border: 1px dashed #aaa;
display: none;
padding: 4px;
}
.img {
top: 0;
left: 0;
width: 800px;
height: 800px;
position: absolute;
pointer-events: none;
z-index: -1;
}
.imgbox{
width: auto;
position: relative;
}
.canvas {
cursor: url('./brush.ico'), auto;
opacity: 1;
}
</style>
js部分
let record = []
let bkgColor = document.getElementById('color')
let eraser = document.getElementById('eraser')
let img = document.getElementById("scream");
let fontWidth = document.getElementById('fontWidth')
let rubberWidth = document.getElementById('rubberWidth')
let lineNum = document.getElementById('lineNum')
let rubberNum = document.getElementById('rubberNum')
let fontColor = document.getElementById('fontColor')
let canvas = document.getElementById('canvas')
let percentage = document.getElementById('percentage')
let body = document.document || document.body
let clientX,clientY,c,lineWidth,rubberSize,eraserFlag,mode=1,color
let flag,fColor='#000'
c = canvas.getContext('2d')
init()
modeChange = function(e) {
mode = e
init({color})
resetHui(false)
}
eraser.onclick = function() { // 橡皮擦点击事件
eraserFlag = !eraserFlag
if(eraserFlag) {
eraser.innerText='画笔'
canvas.style.cursor = "url('./xp1.ico'), auto"
} else {
eraser.innerText='橡皮擦'
canvas.style.cursor = "url('./brush.ico'), auto"
c.strokeStyle = fColor
}
c.beginPath();
}
bkgColor.onchange = function(e) { // 背景颜色
color = e.target.value
init({color})
resetHui(false)
}
fontColor.onchange = function(e) { // 画笔颜色
fColor = e.target.value
c.beginPath();
c.strokeStyle = fColor
}
fontWidth.onchange = function(e) { // 画笔粗细 选择之后
lineWidth = e.target.value
c.beginPath();
c.lineWidth = lineWidth
}
rubberWidth.onmousemove = function(e) { // 橡皮大小 移动滑块
rubberSize = e.target.value
percentage.innerText = rubberSize+' %'
rubberNum.innerText = rubberSize
}
fontWidth.onmousemove = function(e) { // 画笔粗细 移动滑块
lineWidth = e.target.value
percentage.style.display = 'block'
percentage.innerText = lineWidth+' %'
lineNum.innerText = lineWidth
}
fontWidth.onmouseleave = function(e) { // 画笔粗细 移除滑块
lineWidth = e.target.value
percentage.style.display = 'none'
}
canvas.onmouseenter = function(e) {
if(!eraserFlag) return
// canvas.style.cursor = 'none'
}
canvas.onmousedown = function(e) { // 鼠标按下开始画图
flag = true
if(!eraserFlag) {
c.moveTo(e.clientX,e.clientY)
}
// console.log(e.clientX,e.clientY,'开始');
canvas.onmousemove = function(event) { //鼠标按下移动画图
if(!flag) return
clientX = event.clientX;
clientY = event.clientY
if(!eraserFlag) {
c.lineTo(clientX,clientY)
c.stroke();
// console.log(clientX,clientY,'结束');
// console.log(e.clientX,e.clientY,clientX, clientY, '重回');
record.push({
start: [e.clientX,e.clientY],
end: [clientX, clientY],
strokeStyle: fColor,
lineWidth: lineWidth
})
}else {
if(mode===1) {
c.clearRect(clientX, clientY, rubberSize, rubberSize);
} else {
c.strokeStyle = color
c.fillRect(clientX,clientY,rubberSize,rubberSize);
}
}
}
}
canvas.onmouseup = function() { // 鼠标松开 结束画图
flag = false
c.stroke();
// console.log(record);
}
function start(){
record = []
init()
lineNum.innerText = 0
fontWidth.value = 0
}
function reset(){
init()
resetHui()
}
async function resetHui(needDelay = true) {
let old = []
let strokeStyle,setLineWidth
for(let i=0; i<record.length;i++) {
let item = record[i]
if(!old || (old[0] !== item.start[0] && old[1] !== item.start[1])) {
old[0] = item.start[0]
old[1] = item.start[1]
c.beginPath();
if(!strokeStyle || (strokeStyle !== item.strokeStyle)){
strokeStyle = item.strokeStyle
c.strokeStyle = strokeStyle
}
if(!setLineWidth || (setLineWidth !== item.lineWidth)) {
setLineWidth = item.lineWidth
c.lineWidth = setLineWidth
}
c.moveTo(item.start[0],item.start[1])
}
c.lineTo(item.end[0],item.end[1])
c.stroke();
needDelay && await delay()
}
}
function delay(time = 10) {
return new Promise((res,rej)=>{
setTimeout(function(){
res('随便什么数据');
}, time);
})
}
function init({color='#fff'}={}) {
canvas.width = canvas.width
c.strokeStyle = fontColor // 线条颜色
c.rect(0,0,800,800); // 矩形
c.stroke(); // 线条结束
if (mode===1) { // 模式1为画布模式
c.fillStyle = 'rgba(255, 255, 255, 0)'
} else {
c.fillStyle = color; // 填充颜色 背景色
}
c.fillRect(0,0,800,800); // 填充矩形
c.stroke(); // 线条结束
c.strokeStyle = '#000' // 线条颜色
c.lineWidth = 1 // 线条粗细
c.lineCap = 'square'; // 线条头部形状 扁平 凸起 凹进
}
</script>
第一步: 实现你画我猜画布功能
很简单通过canvas标签和img图片放在div里,img图片和父元素position的定位,然后canvas填充背景色为透明,这样我们就可以获得一个画布背景图了
具体的步骤:
(虽然图片在canvas下方但是为了以防万一我还是加了pointer-events: none;防止图片被点击)
let canvas = document.getElementById('canvas')
c = canvas.getContext('2d') // 创建一个2d的canvas画布
canvas.width = canvas.width // 重新赋值一遍宽度 可以刷新画布
c.strokeStyle='#000' // 线条颜色
c.rect(0,0,800,800); // 绘制矩形
c.fillStyle = 'rgba(255, 255, 255, 0)' // 填充颜色为透明
c.fillRect(0,0,800,800); // 填充颜色大小
c.stroke(); // 线条结束
这样就可以获得一个这样的图片了,现在我们canvas的线条就可以在这个背景上为所欲为了
第二步:开始画画
给canvas加上鼠标点击时候的事件并且再触发鼠标移动的事件,并且通过一个数组记录鼠标的坐标信息(record),通过一个状态记录鼠标是否松开(flag),如果松开了鼠标移动事件就不再执行,通过一个状态来控制是橡皮擦还是画笔(eraserFlag),通过一个状态来控制展示的是背景图还是背景颜色(mode)
record的目的 是回放我们刚刚画的图感觉就像动画一样重新画图
flag的目的 实现点击并且移动才能画画 松开的时候清除
eraserFlag目的 实现橡皮擦和画笔的切换
回放画图过程
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!