feat: 放映模式画板添加荧光笔

This commit is contained in:
pipipi-pikachu 2022-04-23 14:27:08 +08:00
parent b0a4c9dc22
commit 4bd8012425
3 changed files with 70 additions and 39 deletions

View File

@ -17,34 +17,49 @@
@mouseenter="mouseInCanvas = true"
></canvas>
<div
class="pen"
:style="{
left: mouse.x - penSize / 2 + 'px',
top: mouse.y - 36 + penSize / 2 + 'px',
color: color,
}"
v-if="mouseInCanvas && model === 'pen'"
><IconWrite class="icon" size="36" /></div>
<div
class="eraser"
:style="{
left: mouse.x - rubberSize / 2 + 'px',
top: mouse.y - rubberSize / 2 + 'px',
width: rubberSize + 'px',
height: rubberSize + 'px',
}"
v-if="mouseInCanvas && model === 'eraser'"
></div>
<template v-if="mouseInCanvas">
<div
class="eraser"
:style="{
left: mouse.x - rubberSize / 2 + 'px',
top: mouse.y - rubberSize / 2 + 'px',
width: rubberSize + 'px',
height: rubberSize + 'px',
}"
v-if="model === 'eraser'"
></div>
<div
class="pen"
:style="{
left: mouse.x - penSize / 2 + 'px',
top: mouse.y - 36 + penSize / 2 + 'px',
color: color,
}"
v-if="model === 'pen'"
>
<IconWrite class="icon" size="36" v-if="model === 'pen'" />
</div>
<div
class="pen"
:style="{
left: mouse.x - markSize / 2 + 'px',
top: mouse.y + 'px',
color: color,
}"
v-if="model === 'mark'"
>
<IconHighLight class="icon" size="36" v-if="model === 'mark'" />
</div>
</template>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, onUnmounted, PropType, ref } from 'vue'
import { computed, defineComponent, onMounted, onUnmounted, PropType, ref, watch } from 'vue'
const penSize = 6
const rubberSize = 80
const markSize = 25
export default defineComponent({
name: 'writing-board',
@ -54,7 +69,7 @@ export default defineComponent({
default: '#ffcc00',
},
model: {
type: String as PropType<'pen' | 'eraser'>,
type: String as PropType<'pen' | 'eraser' | 'mark'>,
default: 'pen',
},
blackboard: {
@ -119,6 +134,20 @@ export default defineComponent({
}
onMounted(initCanvas)
// canvas ctx
const updateCtx = () => {
if (!ctx) return
if (props.model === 'mark') {
ctx.globalCompositeOperation = 'xor'
ctx.globalAlpha = 0.5
}
else if (props.model === 'pen') {
ctx.globalCompositeOperation = 'source-over'
ctx.globalAlpha = 1
}
}
watch(() => props.model, updateCtx)
//
const draw = (posX: number, posY: number, lineWidth: number) => {
if (!ctx) return
@ -205,9 +234,10 @@ export default defineComponent({
draw(x, y, lineWidth)
lastLineWidth = lineWidth
}
else if (props.model === 'mark') draw(x, y, markSize)
else erase(x, y)
lastPos = {x, y}
lastPos = { x, y }
lastTime = new Date().getTime()
}
@ -266,6 +296,7 @@ export default defineComponent({
mouseInCanvas,
penSize,
rubberSize,
markSize,
writingBoardRef,
canvasRef,
canvasWidth,

View File

@ -96,6 +96,7 @@ import {
Power,
ListView,
Magic,
HighLight,
} from '@icon-park/vue-next'
export default {
@ -215,6 +216,7 @@ export default {
app.component('IconPower', Power)
app.component('IconListView', ListView)
app.component('IconMagic', Magic)
app.component('IconHighLight', HighLight)
// 视频播放器
app.component('IconPause', Pause)

View File

@ -16,10 +16,13 @@
<div class="tools" :style="position">
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.3" title="画笔">
<div class="btn" :class="{ 'active': writingBoardModel === 'pen' }" @click="changePen()"><IconWrite class="icon" /></div>
<div class="btn" :class="{ 'active': writingBoardModel === 'pen' }" @click="changeModel('pen')"><IconWrite class="icon" /></div>
</Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.3" title="荧光笔">
<div class="btn" :class="{ 'active': writingBoardModel === 'mark' }" @click="changeModel('mark')"><IconHighLight class="icon" /></div>
</Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.3" title="橡皮擦">
<div class="btn" :class="{ 'active': writingBoardModel === 'eraser' }" @click="changeEraser()"><IconErase class="icon" /></div>
<div class="btn" :class="{ 'active': writingBoardModel === 'eraser' }" @click="changeModel('eraser')"><IconErase class="icon" /></div>
</Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.3" title="清除墨迹">
<div class="btn" @click="clearCanvas()"><IconClear class="icon" /></div>
@ -48,7 +51,7 @@
import { defineComponent, PropType, ref } from 'vue'
import WritingBoard from '@/components/WritingBoard.vue'
const writingBoardColors = ['#000000', '#ffffff', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']
const writingBoardColors = ['#000000', '#ffffff', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c', '#ffff3a']
interface Position {
left?: number | string;
@ -57,6 +60,8 @@ interface Position {
bottom?: number | string;
}
type WritingBoardModel = 'pen' | 'mark' | 'eraser'
export default defineComponent({
name: 'writing-board-tool',
emits: ['close'],
@ -83,17 +88,11 @@ export default defineComponent({
setup(props, { emit }) {
const writingBoardRef = ref()
const writingBoardColor = ref('#e2534d')
const writingBoardModel = ref<'pen' | 'eraser'>('pen')
const writingBoardModel = ref<WritingBoardModel>('pen')
const blackboard = ref(false)
//
const changePen = () => {
writingBoardModel.value = 'pen'
}
//
const changeEraser = () => {
writingBoardModel.value = 'eraser'
const changeModel = (model: WritingBoardModel) => {
writingBoardModel.value = model
}
//
@ -101,9 +100,9 @@ export default defineComponent({
writingBoardRef.value.clearCanvas()
}
//
//
const changeColor = (color: string) => {
if (writingBoardModel.value !== 'pen') writingBoardModel.value = 'pen'
if (writingBoardModel.value === 'eraser') writingBoardModel.value = 'pen'
writingBoardColor.value = color
}
@ -118,8 +117,7 @@ export default defineComponent({
writingBoardColor,
writingBoardModel,
blackboard,
changePen,
changeEraser,
changeModel,
clearCanvas,
changeColor,
closeWritingBoard,