Web/vueVersion/src/components/Whiteboard/Stamps.vue (218 lines of code) (raw):
<template>
<a-popover placement="right" trigger="click">
<template #content>
<div class="dingrtc-wb-popup">
<div class="dingrtc-wb-popup__item dingrtc-wb-popup__item--fixedWith">
<div
class="dingrtc-wb-popup__item__list"
v-for="stamp in stamps"
:key="stamp.id"
>
<div
:class="{
'dingrtc-wb-popup__item__list__item': true,
'dingrtc-wb-popup__item__list__item--resizable': stamp.resizable,
'dingrtc-wb-popup__item__list__item--selected':
selectedStamp === stamp.id
}"
@click="selectStamp(stamp.id)"
>
<img :src="stamp.url" :alt="stamp.id" />
</div>
</div>
</div>
</div>
</template>
<slot></slot>
</a-popover>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { RtcWhiteboard } from '@dingrtc/whiteboard';
interface IProps {
whiteboard: RtcWhiteboard;
}
const props = defineProps<IProps>();
defineEmits<{ (e: 'select'): void }>();
const stamps = ref([
{
id: 'star',
url: 'https://img.alicdn.com/imgextra/i3/O1CN01Yxeqol2002jcyPMVv_!!6000000006786-2-tps-32-29.png',
resizable: false
},
{
id: 'cross',
url: 'https://img.alicdn.com/imgextra/i2/O1CN01WBoIQY28QAFSRvjXG_!!6000000007926-2-tps-32-32.png',
resizable: false
},
{
id: 'heart',
url: 'https://img.alicdn.com/imgextra/i4/O1CN01EM5zzt1DOr1DbI7xh_!!6000000000207-2-tps-32-32.png',
resizable: false
},
{
id: 'zan',
url: 'https://img.alicdn.com/imgextra/i2/O1CN012fbuSE1xgglc5aekA_!!6000000006473-2-tps-32-32.png',
resizable: false
},
{
id: 'tick',
url: 'https://img.alicdn.com/imgextra/i1/O1CN01pzfExM1FxK3bfznLG_!!6000000000553-2-tps-32-32.png',
resizable: false
},
{
id: 'rocket',
url: 'https://img.alicdn.com/imgextra/i4/O1CN01rhHylr1Dlkp20GgKY_!!6000000000257-2-tps-128-128.png',
resizable: true
},
{
id: 'house',
url: 'https://img.alicdn.com/imgextra/i2/O1CN012eL3Vy1ZCPoBnZouA_!!6000000003158-2-tps-128-128.png',
resizable: true
}
]);
const selectedStamp = ref('');
const selectStamp = (id: string) => {
selectedStamp.value = id;
props.whiteboard.setStamp(id);
};
onMounted(() => {
stamps.value.forEach(stamp => {
props.whiteboard.addStamp(stamp.id, stamp.url, stamp.resizable);
});
});
</script>
<style lang="less" scoped>
.dingrtc-wb-tb {
&__item {
font-size: 18px;
display: inline-flex;
width: 30px;
height: 30px;
padding: 2px;
justify-content: center;
align-items: center;
border-radius: 5px;
cursor: pointer;
margin: 1px 0;
color: #333;
position: relative;
&:hover {
background-color: lightgray;
}
&--selected {
// background-color: @deep-grey;
color: #0899f9;
&:hover {
background-color: lightgray;
}
}
&__triangle {
position: absolute;
right: 2px;
bottom: 3px;
border: 3px solid transparent;
border-right-color: #333;
border-bottom-color: #333;
&--selected {
position: absolute;
right: 2px;
bottom: 3px;
border: 3px solid transparent;
border-right-color: #0899f9;
border-bottom-color: #0899f9;
}
}
}
}
.dingrtc-wb-popup {
font-size: 12px;
pointer-events: all;
button:hover {
background-color: #eee;
}
&__item {
display: flex;
align-items: center;
flex-wrap: wrap;
button {
font-size: 12px !important;
}
&__label {
font-size: 12px;
padding-right: 5px;
}
&__list {
width: 25%;
display: flex;
justify-content: center;
padding: 8px 0;
&__item {
cursor: pointer;
width: 30px;
height: 30px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
border-radius: 3px;
&--resizable {
&::before,
&::after {
position: absolute;
content: '';
width: 0;
height: 0;
border: 3px solid rgba(0, 0, 0, 0.3);
}
&::before {
left: 3px;
top: 3px;
border-bottom-color: transparent;
border-right-color: transparent;
}
&::after {
right: 3px;
bottom: 3px;
border-top-color: transparent;
border-left-color: transparent;
}
}
&--selected {
box-shadow: 0 0 1px 2px rgba(0, 0, 0, 0.1);
}
img {
width: 16px;
height: 16px;
}
}
}
&--no-flex {
display: block;
}
&--fixedWith {
width: 160px;
}
}
&__item ~ &__item {
margin-top: 5px;
position: relative;
line-height: 32px;
padding-top: 5px;
&::before {
position: absolute;
content: '';
width: 100%;
height: 1px;
background-color: #eee;
top: 0;
}
}
&__item2 {
display: flex;
align-items: center;
flex-wrap: wrap;
width: 160px;
}
}
</style>