refactor: 画笔工具重构,墨迹自适应屏幕缩放

This commit is contained in:
pipipi-pikachu 2022-03-23 21:57:49 +08:00
parent e315518bec
commit 7ea0fd4286
3 changed files with 81 additions and 21 deletions

View File

@ -3,6 +3,10 @@
<div class="blackboard" v-if="blackboard"></div> <div class="blackboard" v-if="blackboard"></div>
<canvas class="canvas" ref="canvasRef" <canvas class="canvas" ref="canvasRef"
:style="{
width: canvasWidth + 'px',
height: canvasHeight + 'px',
}"
@mousedown="$event => handleMousedown($event)" @mousedown="$event => handleMousedown($event)"
@mousemove="$event => handleMousemove($event)" @mousemove="$event => handleMousemove($event)"
@mouseup="handleMouseup()" @mouseup="handleMouseup()"
@ -37,7 +41,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted, PropType, reactive, ref } from 'vue' import { computed, defineComponent, onMounted, onUnmounted, PropType, reactive, ref } from 'vue'
const penSize = 6 const penSize = 6
const rubberSize = 80 const rubberSize = 80
@ -86,6 +90,25 @@ export default defineComponent({
// //
const mouseInCanvas = ref(false) const mouseInCanvas = ref(false)
// canvas
const canvasWidth = ref(0)
const canvasHeight = ref(0)
const widthScale = computed(() => canvasRef.value ? canvasWidth.value / canvasRef.value.width : 1)
const heightScale = computed(() => canvasRef.value ? canvasHeight.value / canvasRef.value.height : 1)
const updateCanvasSize = () => {
if (!writingBoardRef.value) return
canvasWidth.value = writingBoardRef.value.clientWidth
canvasHeight.value = writingBoardRef.value.clientHeight
}
const resizeObserver = new ResizeObserver(updateCanvasSize)
onMounted(() => {
if (writingBoardRef.value) resizeObserver.observe(writingBoardRef.value)
})
onUnmounted(() => {
if (writingBoardRef.value) resizeObserver.unobserve(writingBoardRef.value)
})
// //
const initCanvas = () => { const initCanvas = () => {
@ -97,9 +120,6 @@ export default defineComponent({
canvasRef.value.width = writingBoardRef.value.clientWidth canvasRef.value.width = writingBoardRef.value.clientWidth
canvasRef.value.height = writingBoardRef.value.clientHeight canvasRef.value.height = writingBoardRef.value.clientHeight
canvasRef.value.style.width = writingBoardRef.value.clientWidth + 'px'
canvasRef.value.style.height = writingBoardRef.value.clientHeight + 'px'
ctx.lineCap = 'round' ctx.lineCap = 'round'
ctx.lineJoin = 'round' ctx.lineJoin = 'round'
} }
@ -197,28 +217,40 @@ export default defineComponent({
lastTime = new Date().getTime() lastTime = new Date().getTime()
} }
// canvas
const getMouseOffsetPosition = (e: MouseEvent | TouchEvent) => {
if (!canvasRef.value) return [0, 0]
const event = e instanceof MouseEvent ? e : e.changedTouches[0]
const canvasRect = canvasRef.value.getBoundingClientRect()
const x = event.pageX - canvasRect.x
const y = event.pageY - canvasRect.y
return [x, y]
}
// //
// / // /
const handleMousedown = (e: MouseEvent | TouchEvent) => { const handleMousedown = (e: MouseEvent | TouchEvent) => {
const x = e instanceof MouseEvent ? e.offsetX : e.changedTouches[0].pageX const [mouseX, mouseY] = getMouseOffsetPosition(e)
const y = e instanceof MouseEvent ? e.offsetY : e.changedTouches[0].pageY const x = mouseX / widthScale.value
const y = mouseY / heightScale.value
isMouseDown = true isMouseDown = true
lastPos = { x, y } lastPos = { x, y }
lastTime = new Date().getTime() lastTime = new Date().getTime()
if (e instanceof TouchEvent) { if (e instanceof TouchEvent) {
updateMousePosition(x, y) updateMousePosition(mouseX, mouseY)
mouseInCanvas.value = true mouseInCanvas.value = true
} }
} }
// / // /
const handleMousemove = (e: MouseEvent | TouchEvent) => { const handleMousemove = (e: MouseEvent | TouchEvent) => {
const x = e instanceof MouseEvent ? e.offsetX : e.changedTouches[0].pageX const [mouseX, mouseY] = getMouseOffsetPosition(e)
const y = e instanceof MouseEvent ? e.offsetY : e.changedTouches[0].pageY const x = mouseX / widthScale.value
const y = mouseY / heightScale.value
updateMousePosition(x, y) updateMousePosition(mouseX, mouseY)
if (isMouseDown) handleMove(x, y) if (isMouseDown) handleMove(x, y)
} }
@ -242,6 +274,8 @@ export default defineComponent({
rubberSize, rubberSize,
writingBoardRef, writingBoardRef,
canvasRef, canvasRef,
canvasWidth,
canvasHeight,
handleMousedown, handleMousedown,
handleMousemove, handleMousemove,
handleMouseup, handleMouseup,
@ -253,13 +287,8 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.writing-board { .writing-board {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 8;
cursor: none; cursor: none;
@include absolute-0();
} }
.blackboard { .blackboard {
width: 100%; width: 100%;
@ -267,11 +296,13 @@ export default defineComponent({
background-color: #0f392b; background-color: #0f392b;
} }
.canvas { .canvas {
@include absolute-0(); position: absolute;
top: 0;
left: 0;
} }
.eraser, .pen { .eraser, .pen {
pointer-events: none; pointer-events: none;
position: fixed; position: absolute;
z-index: 9; z-index: 9;
.icon { .icon {

View File

@ -1,13 +1,18 @@
<template> <template>
<div class="writing-board-tool"> <div class="writing-board-tool">
<teleport to="body"> <div class="writing-board-wrap"
:style="{
width: slideWidth + 'px',
height: slideHeight + 'px',
}"
>
<WritingBoard <WritingBoard
ref="writingBoardRef" ref="writingBoardRef"
:color="writingBoardColor" :color="writingBoardColor"
:blackboard="blackboard" :blackboard="blackboard"
:model="writingBoardModel" :model="writingBoardModel"
/> />
</teleport> </div>
<div class="tools"> <div class="tools">
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.3" title="画笔"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.3" title="画笔">
@ -51,6 +56,16 @@ export default defineComponent({
components: { components: {
WritingBoard, WritingBoard,
}, },
props: {
slideWidth: {
type: Number,
required: true,
},
slideHeight: {
type: Number,
required: true,
},
},
setup(props, { emit }) { setup(props, { emit }) {
const writingBoardRef = ref() const writingBoardRef = ref()
const writingBoardColor = ref('#e2534d') const writingBoardColor = ref('#e2534d')
@ -102,6 +117,15 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.writing-board-tool { .writing-board-tool {
font-size: 12px; font-size: 12px;
z-index: 10;
@include absolute-0();
.writing-board-wrap {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.tools { .tools {
height: 50px; height: 50px;

View File

@ -45,7 +45,12 @@
@close="slideThumbnailModelVisible = false" @close="slideThumbnailModelVisible = false"
/> />
<WritingBoardTool v-if="writingBoardToolVisible" @close="writingBoardToolVisible = false" /> <WritingBoardTool
:slideWidth="slideWidth"
:slideHeight="slideHeight"
v-if="writingBoardToolVisible"
@close="writingBoardToolVisible = false"
/>
<div class="tools-left"> <div class="tools-left">
<IconLeftTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execPrev()" /> <IconLeftTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execPrev()" />