You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

362 lines
7.9 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div
id="wrapper"
class="wrapper vue-ruler-wrapper"
:style="{
width: width + thick + 'px',
height: height + thick + 'px'
}"
>
<i
:class="{
'iconfont-bigscreen': true,
'icon-eye': isShowReferLine,
'icon-eye-close': !isShowReferLine
}"
@click="handleCornerClick"
/>
<SketchRule
:key="scale"
:lang="lang"
:thick="thick"
:scale="scale"
:width="width"
:height="height"
:start-x="startX"
:start-y="startY"
:shadow="shadow"
:hor-line-arr="[...lines.h, ...presetLines.h]"
:ver-line-arr="[...lines.v, ...presetLines.v]"
:palette="Palette"
:is-show-refer-line="isShowReferLine"
:corner-active="cornerActive"
@handleLine="handleLine"
@onCornerClick="handleCornerClick"
/>
<div
id="screens"
ref="screensRef"
:style="{
width: innerWidth + 'px',
height: innerHeight + 'px'
}"
@scroll="throttleScroll"
>
<div
ref="containerRef"
class="screen-container grid-bg"
:style="containerRefStyle"
>
<div
id="canvas"
:style="canvasStyle"
>
<slot />
</div>
</div>
</div>
</div>
</template>
<script>
import SketchRule from 'vue-sketch-ruler'
import { mapState, mapMutations } from 'vuex'
import throttle from 'lodash/throttle'
export default {
components: {
SketchRule
},
props: {
width: {
type: Number,
default: 500
},
height: {
type: Number,
default: 400
},
pageWidth: {
type: Number,
default: 1920
},
pageHeight: {
type: Number,
default: 1080
}
},
data () {
return {
startX: 0,
startY: 0,
lines: {
h: [],
v: []
},
thick: 20,
lang: 'zh-CN', // 中英文
isShowRuler: true, // 显示标尺
isShowReferLine: true, // 显示参考线
cornerActive: true, // 左上角激活状态
Palette: {
bgColor: 'rgba(225,225,225, 0)',
longfgColor: '#BABBBC',
shortfgColor: '#C8CDD0',
fontColor: '#7D8694',
shadowColor: 'transparent',
lineColor: '#0089d0',
borderColor: '#transparent',
cornerActiveColor: 'rgb(235, 86, 72, 0.6)'
},
containerRefStyle: {
width: this.width + 'px',
height: this.height + 'px'
},
innerHeight: 0,
innerWidth: 0
}
},
watch: {
// 缩放改变的时候改变startXstartY
scale (scale) {
// 防抖调用方法
this.throttleScroll()
},
pageWidth (pageWidth) {
if (this.fitZoom === this.zoom) {
this.initZoom()
}
},
pageHeight (pageHeight) {
if (this.fitZoom === this.zoom) {
this.initZoom()
}
}
},
computed: {
...mapState('bigScreen', {
scale: state => state.zoom / 100,
fitZoom: state => state.fitZoom,
zoom: state => state.zoom
}),
presetLines () {
const presetLine = this.$store.state.bigScreen.presetLine
// { type: 'h', site: y || 0 },
const v = presetLine?.filter(p => p.type === 'h')?.map(p => p.site)
const h = presetLine?.filter(p => p.type === 'v')?.map(p => p.site)
return {
h,
v
}
},
shadow () {
return {
x: 0,
y: 0,
width: this.width,
height: this.height
}
},
canvasStyle () {
return {
width: this.width + 'px',
height: this.height + 'px',
transform: `scale(${this.scale})`,
transformOrigin: '0 0 0'
}
}
},
mounted () {
// 监听屏幕改变
this.listenSize()
this.initRuleHeight()
this.throttleScroll()
},
methods: {
...mapMutations('bigScreen', [
'changeZoom',
'changeFitZoom'
]),
listenSize () {
window.onresize = throttle(() => {
this.initRuleHeight()
}, 100)
},
initRuleHeight () {
setTimeout(() => {
const screensRect = document
.querySelector('.grid-wrap-box')
?.getBoundingClientRect()
if (!screensRect) {
return
}
// 30是grid-wrap-box的底部工具栏高度
this.innerHeight = screensRect.height
this.innerWidth = screensRect.width
this.diffX = this.width - screensRect.width
this.diffY = this.height - screensRect.height
this.containerRefStyle = {
width: this.diffX > 0 ? ((this.width + this.diffX + this.thick + 30) + 'px') : (this.width + 'px'),
height: this.diffY > 0 ? ((this.height + this.diffY + this.thick + 30) + 'px') : (this.height + 'px')
}
if (this.fitZoom === this.zoom) {
this.initZoom()
}
})
},
handleLine (lines) {
this.lines = lines
},
handleCornerClick () {
this.isShowReferLine = !this.isShowReferLine
this.cornerActive = !this.cornerActive
},
throttleScroll () {
throttle(() => {
this.handleScroll()
}, 100)()
},
handleScroll () {
const screensRect = document
.querySelector('#screens')
.getBoundingClientRect()
const canvasRect = document
.querySelector('#canvas')
.getBoundingClientRect()
// 标尺开始的刻度
const startX = (screensRect.left + this.thick - canvasRect.left) / this.scale
const startY = (screensRect.top + this.thick - canvasRect.top) / this.scale
this.startX = startX >> 0
this.startY = startY >> 0
this.$emit('changeStart', {
x: this.startX * this.scale + 50 - this.thick,
y: this.startY * this.scale + 50 - this.thick
})
},
// 保证画布能完整展示大屏
initZoom () {
// 横向比例
const xRadio = this.innerWidth / (this.pageWidth + 120)
// 纵向比例
const yRadio = this.innerHeight / (this.pageHeight + 120)
// 取最小的适应比例
const scale = Math.floor(Math.min(xRadio * 100, yRadio * 100))
if (scale < 100) {
this.changeZoom(scale)
this.changeFitZoom(scale)
} else {
this.changeZoom(100)
this.changeFitZoom(100)
}
}
}
}
</script>
<style lang="scss" scoped>
@import '../../BigScreenDesign/fonts/iconfont.css';
.wrapper {
box-sizing: border-box;
position: absolute;
.iconfont-bigscreen {
position: absolute;
left: 0;
top: 0;
font-size: 16px;
color: #fff;
z-index: 999;
cursor: pointer;
}
}
#screens {
position: absolute;
overflow: scroll;
// 滚动条美化,始终在最下方和最右方
&::-webkit-scrollbar {
width: 10px;
height: 10px;
}
&::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: var(--bs-el-background-2) !important;
}
&::-webkit-scrollbar-track {
border-radius: 10px;
background-color: transparent !important;
}
}
.screen-container {
position: absolute;
width: 6000px;
height: 6000px;
}
.scale-value {
position: absolute;
left: 0;
bottom: 100%;
}
.button {
position: absolute;
left: 100px;
bottom: 100%;
}
.button-ch {
position: absolute;
left: 200px;
bottom: 100%;
}
.button-en {
position: absolute;
left: 230px;
bottom: 100%;
}
#canvas {
position: absolute;
top: 50px;
left: 50px;
}
::v-deep .line {
border-left: 1px dashed #0089d0 !important;
border-top: 1px dashed #0089d0 !important;
}
::v-deep.action {
.value {
background: var(--bs-el-color-primary);
padding: 4px;
color: #fff;
}
.del {
color: var(--bs-el-color-primary);
}
}
::v-deep .ruler, ::v-deep .corner {
background: var(--bs-background-1);
}
::v-deep .corner {
z-index: 999;
background: var(--bs-background-1) !important;
}
::v-deep .mb-ruler {
z-index: 998
}
.grid-bg {
background-color: #2a2e33 !important;
background-image: url(./images/canvas-bg.png);
background-repeat: repeat;
word-spacing: 10px;
}
</style>