forked from github/dataease
feat: 画布升级 增加矩阵 边界 对齐 吸附等功能
This commit is contained in:
parent
704d86adf4
commit
dba5eeb571
@ -1,6 +1,8 @@
|
||||
package io.dataease.controller.handler;
|
||||
|
||||
import io.dataease.controller.ResultHolder;
|
||||
import io.dataease.controller.handler.annotation.I18n;
|
||||
import io.dataease.i18n.Translator;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.web.servlet.error.ErrorAttributes;
|
||||
@ -66,7 +68,8 @@ public class GlobalExceptionHandler implements ErrorController {
|
||||
errorMessage = "The server responds " + code + " but no detailed message.";
|
||||
}
|
||||
}
|
||||
return ResultHolder.error(errorMessage);
|
||||
|
||||
return ResultHolder.error(Translator.get(errorMessage));
|
||||
}
|
||||
|
||||
protected Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
|
||||
|
@ -239,7 +239,7 @@ i18n_processing_data=Processing data now, Refresh later
|
||||
i18n_union_already_exists=Union relation already exists
|
||||
i18n_union_field_exists=The same field can't in two dataset
|
||||
i18n_cron_time_error=Start time can't greater then end time
|
||||
i18n_auth_source_be_canceled=This Auth Resource Already Be Canceled
|
||||
i18n_auth_source_be_canceled=This Auth Resource Already Be Canceled,Please Connect Admin
|
||||
i18n_username_exists=ID is already exists
|
||||
i18n_ds_name_exists=Datasource name used
|
||||
i18n_sync_job_exists=There is already a synchronization task running, please try again later
|
||||
|
@ -239,7 +239,7 @@ i18n_processing_data=正在处理数据,稍后刷新
|
||||
i18n_union_already_exists=关联关系已存在
|
||||
i18n_union_field_exists=两个数据集之间关联不能出现多次相同字段
|
||||
i18n_cron_time_error=开始时间不能大于结束时间
|
||||
i18n_auth_source_be_canceled=当前资源授权权限已经被取消
|
||||
i18n_auth_source_be_canceled=本用户当前资源所有授权权限已经被取消,如需再次开通,请联系管理员
|
||||
i18n_username_exists=用户 ID 已存在
|
||||
i18n_ds_name_exists=数据源名称已被使用
|
||||
i18n_sync_job_exists=已经有同步任务在运行,稍后重试
|
||||
|
@ -241,7 +241,7 @@ i18n_processing_data=正在處理數據,稍後刷新
|
||||
i18n_union_already_exists=關聯關系已存在
|
||||
i18n_union_field_exists=兩個數據集之間關聯不能出現多次相同字段
|
||||
i18n_cron_time_error=開始時間不能大於結束時間
|
||||
i18n_auth_source_be_canceled=當前資源授權權限已經被取消
|
||||
i18n_auth_source_be_canceled=本用户当前资源所有授权权限已经被取消,如需再次开通,请联系管理员
|
||||
i18n_username_exists=用戶ID已存在
|
||||
i18n_ds_name_exists=數據源名稱已被使用
|
||||
i18n_sync_job_exists=已經有同步任務在運行,稍後重試
|
||||
|
1597
frontend/src/components/DeDrag/index.vue
Normal file
1597
frontend/src/components/DeDrag/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
26
frontend/src/components/DeDrag/option.js
Normal file
26
frontend/src/components/DeDrag/option.js
Normal file
@ -0,0 +1,26 @@
|
||||
export const events = {
|
||||
mouse: {
|
||||
start: 'mousedown',
|
||||
move: 'mousemove',
|
||||
stop: 'mouseup'
|
||||
},
|
||||
touch: {
|
||||
start: 'touchstart',
|
||||
move: 'touchmove',
|
||||
stop: 'touchend'
|
||||
}
|
||||
}
|
||||
// 禁止用户选取
|
||||
export const userSelectNone = {
|
||||
userSelect: 'none',
|
||||
MozUserSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
MsUserSelect: 'none'
|
||||
}
|
||||
// 用户选中自动
|
||||
export const userSelectAuto = {
|
||||
userSelect: 'auto',
|
||||
MozUserSelect: 'auto',
|
||||
WebkitUserSelect: 'auto',
|
||||
MsUserSelect: 'auto'
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<svg class="grid" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<pattern id="smallGrid" width="7.236328125" height="7.236328125" patternUnits="userSpaceOnUse">
|
||||
<!-- <pattern id="smallGrid" width="5" height="5" patternUnits="userSpaceOnUse">-->
|
||||
<!-- <path-->
|
||||
<!-- d="M 5 0 L 0 0 0 5"-->
|
||||
<!-- fill="none"-->
|
||||
<!-- stroke="rgba(207, 207, 207, 0.3)"-->
|
||||
<!-- stroke-width="1"-->
|
||||
<!-- />-->
|
||||
<!-- </pattern>-->
|
||||
<pattern id="grid" :width="matrixStyle.width" :height="matrixStyle.height" patternUnits="userSpaceOnUse">
|
||||
<rect :width="matrixStyle.width" :height="matrixStyle.height" fill="url(#smallGrid)" />
|
||||
<path
|
||||
d="M 7.236328125 0 L 0 0 0 7.236328125"
|
||||
fill="none"
|
||||
stroke="rgba(207, 207, 207, 0.3)"
|
||||
stroke-width="1"
|
||||
/>
|
||||
</pattern>
|
||||
<pattern id="grid" width="36.181640625" height="36.181640625" patternUnits="userSpaceOnUse">
|
||||
<rect width="36.181640625" height="36.181640625" fill="url(#smallGrid)" />
|
||||
<path
|
||||
d="M 36.181640625 0 L 0 0 0 36.181640625"
|
||||
:d="pathD"
|
||||
fill="none"
|
||||
stroke="rgba(186, 186, 186, 0.5)"
|
||||
stroke-width="1"
|
||||
@ -23,6 +23,28 @@
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: {
|
||||
matrixStyle: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
pathD: function() {
|
||||
return 'M ' + this.matrixStyle.width + ' 0 L 0 0 0 ' + this.matrixStyle.height
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid {
|
||||
position: absolute;
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="showDrag"
|
||||
id="editor"
|
||||
class="editor"
|
||||
:class="{ edit: isEdit }"
|
||||
@ -8,18 +9,27 @@
|
||||
@mousedown="handleMouseDown"
|
||||
>
|
||||
<!-- 网格线 -->
|
||||
<Grid />
|
||||
|
||||
<Grid v-if="canvasStyleData.auxiliaryMatrix" :matrix-style="matrixStyle" />
|
||||
<!--页面组件列表展示-->
|
||||
<Shape
|
||||
<de-drag
|
||||
v-for="(item, index) in componentData"
|
||||
:key="item.id"
|
||||
:index="index"
|
||||
:x="getShapeStyleIntDeDrag(item.style,'left')"
|
||||
:y="getShapeStyleIntDeDrag(item.style,'top')"
|
||||
:w="getShapeStyleIntDeDrag(item.style,'width')"
|
||||
:h="getShapeStyleIntDeDrag(item.style,'height')"
|
||||
:r="item.style.rotate"
|
||||
:parent="true"
|
||||
:rotatable="rotatable"
|
||||
:default-style="getShapeStyleInt(item.style)"
|
||||
:style="getShapeStyle(item.style)"
|
||||
:active="item === curComponent"
|
||||
:element="item"
|
||||
:index="index"
|
||||
:class="{ lock: item.isLock }"
|
||||
class-name-active="de-drag-active"
|
||||
:class="{'gap_class':canvasStyleData.panel.gap==='yes'}"
|
||||
:snap="true"
|
||||
:snap-tolerance="5"
|
||||
@refLineParams="getRefLineParams"
|
||||
>
|
||||
<component
|
||||
:is="item.component"
|
||||
@ -63,19 +73,33 @@
|
||||
:element="item"
|
||||
@input="handleInput"
|
||||
/> -->
|
||||
</Shape>
|
||||
</de-drag>
|
||||
<!-- 右击菜单 -->
|
||||
<ContextMenu />
|
||||
<!-- 标线 (临时去掉标线 吸附等功能)-->
|
||||
<!-- <MarkLine />-->
|
||||
<!-- 选中区域 -->
|
||||
<Area v-show="isShowArea" :start="start" :width="width" :height="height" />
|
||||
<!-- <Area v-show="isShowArea" :start="start" :width="width" :height="height" />-->
|
||||
|
||||
<span
|
||||
v-for="(item, index) in vLine"
|
||||
v-show="item.display"
|
||||
:key="'v_'+index"
|
||||
class="ref-line v-line"
|
||||
:style="{
|
||||
left: item.position,
|
||||
top: item.origin,
|
||||
height: item.lineLength,
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import Shape from './Shape'
|
||||
import DeDrag from '@/components/DeDrag'
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { getStyle, getComponentRotatedStyle } from '@/components/canvas/utils/style'
|
||||
import { $ } from '@/components/canvas/utils/utils'
|
||||
@ -89,7 +113,7 @@ import { Condition } from '@/components/widget/bean/Condition'
|
||||
import bus from '@/utils/bus'
|
||||
|
||||
export default {
|
||||
components: { Shape, ContextMenu, MarkLine, Area, Grid },
|
||||
components: { Shape, ContextMenu, MarkLine, Area, Grid, DeDrag },
|
||||
props: {
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
@ -128,7 +152,23 @@ export default {
|
||||
needToChangeWidth: [
|
||||
'left',
|
||||
'width'
|
||||
]
|
||||
],
|
||||
// private 是否可旋转
|
||||
rotatable: false,
|
||||
// 矩阵大小
|
||||
matrixStyle: {
|
||||
width: 80,
|
||||
height: 20
|
||||
},
|
||||
// 矩阵数量 默认 12 * 24
|
||||
matrixCount: {
|
||||
x: 12,
|
||||
y: 24
|
||||
},
|
||||
customStyleHistory: null,
|
||||
showDrag: true,
|
||||
vLine: [],
|
||||
hLine: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -146,7 +186,6 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
customStyle() {
|
||||
let style = {
|
||||
width: this.format(this.canvasStyleData.width, this.scaleWidth) + 'px',
|
||||
@ -327,19 +366,26 @@ export default {
|
||||
handleContextMenu(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
|
||||
// 计算菜单相对于编辑器的位移
|
||||
let target = e.target
|
||||
let top = e.offsetY
|
||||
let left = e.offsetX
|
||||
while (target instanceof SVGElement) {
|
||||
target = target.parentNode
|
||||
}
|
||||
let top = 0
|
||||
let left = 0
|
||||
// 如果档期有计划的组件 坐标取当前组件的加上偏移量
|
||||
if (this.curComponent && !target.className.includes('editor')) {
|
||||
top = this.curComponent.style.top * this.scaleHeight / 100 + e.offsetY
|
||||
left = this.curComponent.style.left * this.scaleWidth / 100 + e.offsetX
|
||||
} else {
|
||||
// 计算菜单相对于编辑器的位移
|
||||
top = e.offsetY
|
||||
left = e.offsetX
|
||||
|
||||
while (!target.className.includes('editor')) {
|
||||
left += target.offsetLeft
|
||||
top += target.offsetTop
|
||||
target = target.parentNode
|
||||
while (!target.className.includes('editor')) {
|
||||
left += target.offsetLeft
|
||||
top += target.offsetTop
|
||||
target = target.parentNode
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.commit('showContextMenu', { top, left })
|
||||
@ -443,11 +489,62 @@ export default {
|
||||
}
|
||||
},
|
||||
changeScale() {
|
||||
// 获取当前宽高(宽高改变后重新渲染画布)
|
||||
const style = {
|
||||
width: this.format(this.canvasStyleData.width, this.scaleWidth) + 'px',
|
||||
height: this.format(this.canvasStyleData.height, this.scaleHeight) + 'px'
|
||||
}
|
||||
if (this.customStyleHistory && this.customStyleHistory !== style) {
|
||||
this.showDrag = false
|
||||
this.$nextTick(() => (this.showDrag = true))
|
||||
}
|
||||
this.customStyleHistory = style
|
||||
|
||||
if (this.canvasStyleData.matrixCount) {
|
||||
this.matrixCount = this.canvasStyleData.matrixCount
|
||||
}
|
||||
if (this.outStyle.width && this.outStyle.height) {
|
||||
// 矩阵计算
|
||||
if (!this.canvasStyleData.selfAdaption) {
|
||||
this.matrixStyle.width = this.canvasStyleData.width / this.matrixCount.x
|
||||
this.matrixStyle.height = this.canvasStyleData.height / this.matrixCount.y
|
||||
} else {
|
||||
this.matrixStyle.width = this.outStyle.width / this.matrixCount.x
|
||||
this.matrixStyle.height = this.outStyle.height / this.matrixCount.y
|
||||
}
|
||||
this.scaleWidth = parseInt(this.outStyle.width * 100 / this.canvasStyleData.width)
|
||||
this.scaleHeight = parseInt(this.outStyle.height * 100 / this.canvasStyleData.height)
|
||||
this.$store.commit('setCurCanvasScale', { scaleWidth: this.scaleWidth, scaleHeight: this.scaleHeight })
|
||||
this.$store.commit('setCurCanvasScale',
|
||||
{
|
||||
scaleWidth: this.scaleWidth,
|
||||
scaleHeight: this.scaleHeight,
|
||||
matrixStyleWidth: this.matrixStyle.width,
|
||||
matrixStyleHeight: this.matrixStyle.height
|
||||
})
|
||||
}
|
||||
},
|
||||
getShapeStyleIntDeDrag(style, prop) {
|
||||
if (prop === 'rotate') {
|
||||
return style['rotate']
|
||||
}
|
||||
if (prop === 'width') {
|
||||
return this.format(style['width'], this.scaleWidth)
|
||||
}
|
||||
if (prop === 'left') {
|
||||
return this.format(style['left'], this.scaleWidth)
|
||||
}
|
||||
if (prop === 'height') {
|
||||
return this.format(style['height'], this.scaleHeight)
|
||||
}
|
||||
if (prop === 'top') {
|
||||
return this.format(style['top'], this.scaleHeight)
|
||||
}
|
||||
},
|
||||
getRefLineParams(params) {
|
||||
console.log(params)
|
||||
const { vLine, hLine } = params
|
||||
this.vLine = vLine
|
||||
this.hLine = hLine
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -456,7 +553,7 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.editor {
|
||||
position: relative;
|
||||
background: #fff;
|
||||
/*background: #fff;*/
|
||||
margin: auto;
|
||||
background-size:100% 100% !important;
|
||||
|
||||
@ -465,10 +562,35 @@ export default {
|
||||
}
|
||||
}
|
||||
.edit {
|
||||
outline: 1px solid gainsboro;
|
||||
.component {
|
||||
outline: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.gap_class{
|
||||
padding:3px;
|
||||
}
|
||||
|
||||
// 拖拽组件样式
|
||||
|
||||
.de-drag-active{
|
||||
outline: 1px solid #70c0ff;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ref-line {
|
||||
position: absolute;
|
||||
background-color: #70c0ff;;
|
||||
z-index: 9999;
|
||||
}
|
||||
.v-line {
|
||||
width: 1px;
|
||||
}
|
||||
.h-line {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -2,6 +2,11 @@
|
||||
<div>
|
||||
<div class="toolbar">
|
||||
|
||||
<div class="canvas-config" style="margin-right: 10px">
|
||||
<el-switch v-model="canvasStyleData.auxiliaryMatrix" :width="35" label="矩阵设计" name="auxiliaryMatrix" />
|
||||
<span>矩阵设计</span>
|
||||
</div>
|
||||
|
||||
<div class="canvas-config" style="margin-right: 10px">
|
||||
<el-switch v-model="canvasStyleData.selfAdaption" :width="35" label="自适应画布区域" name="selfAdaption" />
|
||||
<span>自适应画布区域 </span>
|
||||
|
@ -2,41 +2,41 @@ import { swap } from '@/components/canvas/utils/utils'
|
||||
import toast from '@/components/canvas/utils/toast'
|
||||
|
||||
export default {
|
||||
mutations: {
|
||||
upComponent({ componentData, curComponentIndex }) {
|
||||
// 上移图层 index,表示元素在数组中越往后
|
||||
if (curComponentIndex < componentData.length - 1) {
|
||||
swap(componentData, curComponentIndex, curComponentIndex + 1)
|
||||
} else {
|
||||
toast('已经到顶了')
|
||||
}
|
||||
},
|
||||
|
||||
downComponent({ componentData, curComponentIndex }) {
|
||||
// 下移图层 index,表示元素在数组中越往前
|
||||
if (curComponentIndex > 0) {
|
||||
swap(componentData, curComponentIndex, curComponentIndex - 1)
|
||||
} else {
|
||||
toast('已经到底了')
|
||||
}
|
||||
},
|
||||
|
||||
topComponent({ componentData, curComponentIndex }) {
|
||||
// 置顶
|
||||
if (curComponentIndex < componentData.length - 1) {
|
||||
swap(componentData, curComponentIndex, componentData.length - 1)
|
||||
} else {
|
||||
toast('已经到顶了')
|
||||
}
|
||||
},
|
||||
|
||||
bottomComponent({ componentData, curComponentIndex }) {
|
||||
// 置底
|
||||
if (curComponentIndex > 0) {
|
||||
swap(componentData, curComponentIndex, 0)
|
||||
} else {
|
||||
toast('已经到底了')
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
upComponent({ componentData, curComponentIndex }) {
|
||||
// 上移图层 index,表示元素在数组中越往后
|
||||
if (curComponentIndex < componentData.length - 1) {
|
||||
swap(componentData, curComponentIndex, curComponentIndex + 1)
|
||||
} else {
|
||||
toast('已经到顶了')
|
||||
}
|
||||
},
|
||||
|
||||
downComponent({ componentData, curComponentIndex }) {
|
||||
// 下移图层 index,表示元素在数组中越往前
|
||||
if (curComponentIndex > 0) {
|
||||
swap(componentData, curComponentIndex, curComponentIndex - 1)
|
||||
} else {
|
||||
toast('已经到底了')
|
||||
}
|
||||
},
|
||||
|
||||
topComponent({ componentData, curComponentIndex }) {
|
||||
// 置顶
|
||||
if (curComponentIndex < componentData.length - 1) {
|
||||
swap(componentData, curComponentIndex, componentData.length - 1)
|
||||
} else {
|
||||
toast('已经到顶了')
|
||||
}
|
||||
},
|
||||
|
||||
bottomComponent({ componentData, curComponentIndex }) {
|
||||
// 置底
|
||||
if (curComponentIndex > 0) {
|
||||
swap(componentData, curComponentIndex, 0)
|
||||
} else {
|
||||
toast('已经到底了')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ export default {
|
||||
},
|
||||
|
||||
recordSnapshot(state) {
|
||||
console.log('recordSnapshot')
|
||||
// 添加新的快照
|
||||
state.snapshotData[++state.snapshotIndex] = deepCopy(state.componentData)
|
||||
state.snapshotStyleData[state.snapshotIndex] = deepCopy(state.canvasStyleData)
|
||||
|
@ -952,6 +952,7 @@ export default {
|
||||
close_aided_design: 'Close Component Aided Design',
|
||||
open_style_design: 'Open Style Design',
|
||||
close_style_design: 'Close Style Design',
|
||||
matrix_design: 'Matrix Design',
|
||||
left: 'X-Axis',
|
||||
top: 'Y-Axis',
|
||||
height: 'Height',
|
||||
|
@ -952,6 +952,7 @@ export default {
|
||||
close_aided_design: '关闭组件辅助设计',
|
||||
open_style_design: '打开样式设计',
|
||||
close_style_design: '关闭样式设计',
|
||||
matrix_design: '矩阵设计',
|
||||
left: 'x 坐标',
|
||||
top: 'y 坐标',
|
||||
height: '高',
|
||||
|
@ -952,6 +952,7 @@ export default {
|
||||
close_aided_design: '关闭组件辅助设计',
|
||||
open_style_design: '打开样式设计',
|
||||
close_style_design: '关闭样式设计',
|
||||
matrix_design: '矩阵设计',
|
||||
left: 'x 坐标',
|
||||
top: 'y 坐标',
|
||||
height: '高',
|
||||
|
@ -27,6 +27,7 @@ Vue.use(VueClipboard)
|
||||
Vue.use(widgets)
|
||||
Vue.prototype.$api = api
|
||||
|
||||
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
Vue.prototype.$echarts = echarts
|
||||
|
@ -72,7 +72,7 @@ const data = {
|
||||
},
|
||||
|
||||
setCurComponent(state, { component, index }) {
|
||||
// console.log('curComponent' + JSON.stringify(component))
|
||||
console.log('curComponent' + JSON.stringify(component))
|
||||
state.curComponent = component
|
||||
state.curComponentIndex = index
|
||||
},
|
||||
@ -82,12 +82,12 @@ const data = {
|
||||
},
|
||||
|
||||
setShapeStyle({ curComponent, canvasStyleData, curCanvasScale }, { top, left, width, height, rotate }) {
|
||||
if (top) curComponent.style.top = parseInt(canvasStyleData.selfAdaption ? (top * 100 / curCanvasScale.scaleHeight) : top)
|
||||
if (left) curComponent.style.left = parseInt(canvasStyleData.selfAdaption ? (left * 100 / curCanvasScale.scaleWidth) : left)
|
||||
if (width) curComponent.style.width = parseInt(canvasStyleData.selfAdaption ? (width * 100 / curCanvasScale.scaleWidth) : width)
|
||||
if (height) curComponent.style.height = parseInt(canvasStyleData.selfAdaption ? (height * 100 / curCanvasScale.scaleHeight) : height)
|
||||
if (rotate) curComponent.style.rotate = rotate
|
||||
// console.log('setShapeStyle' + JSON.stringify(curComponent))
|
||||
if (top || top === 0) curComponent.style.top = parseInt(canvasStyleData.selfAdaption ? (top * 100 / curCanvasScale.scaleHeight) : top)
|
||||
if (left || left === 0) curComponent.style.left = parseInt(canvasStyleData.selfAdaption ? (left * 100 / curCanvasScale.scaleWidth) : left)
|
||||
if (width || width === 0) curComponent.style.width = parseInt(canvasStyleData.selfAdaption ? (width * 100 / curCanvasScale.scaleWidth) : width)
|
||||
if (height || height === 0) curComponent.style.height = parseInt(canvasStyleData.selfAdaption ? (height * 100 / curCanvasScale.scaleHeight) : height)
|
||||
if (rotate || rotate === 0) curComponent.style.rotate = rotate
|
||||
// console.log('setShapeStyle:curComponent' + 'top:' + top + ';left:' + left + '====' + JSON.stringify(curComponent))
|
||||
},
|
||||
|
||||
setShapeSingleStyle({ curComponent }, { key, value }) {
|
||||
|
60
frontend/src/utils/dom.js
Normal file
60
frontend/src/utils/dom.js
Normal file
@ -0,0 +1,60 @@
|
||||
import { isFunction } from './fns'
|
||||
|
||||
// 将选择器与父元素匹配
|
||||
export function matchesSelectorToParentElements(el, selector, baseNode) {
|
||||
let node = el
|
||||
|
||||
const matchesSelectorFunc = [
|
||||
'matches',
|
||||
'webkitMatchesSelector',
|
||||
'mozMatchesSelector',
|
||||
'msMatchesSelector',
|
||||
'oMatchesSelector'
|
||||
].find(func => isFunction(node[func]))
|
||||
|
||||
if (!isFunction(node[matchesSelectorFunc])) return false
|
||||
|
||||
do {
|
||||
if (node[matchesSelectorFunc](selector)) return true
|
||||
if (node === baseNode) return false
|
||||
node = node.parentNode
|
||||
} while (node)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function getComputedSize($el) {
|
||||
const style = window.getComputedStyle($el)
|
||||
|
||||
return [
|
||||
parseFloat(style.getPropertyValue('width'), 10),
|
||||
parseFloat(style.getPropertyValue('height'), 10)
|
||||
]
|
||||
}
|
||||
// 添加事件
|
||||
export function addEvent(el, event, handler) {
|
||||
if (!el) {
|
||||
return
|
||||
}
|
||||
if (el.attachEvent) {
|
||||
el.attachEvent('on' + event, handler)
|
||||
} else if (el.addEventListener) {
|
||||
el.addEventListener(event, handler, true)
|
||||
} else {
|
||||
el['on' + event] = handler
|
||||
}
|
||||
}
|
||||
|
||||
// 删除事件
|
||||
export function removeEvent(el, event, handler) {
|
||||
if (!el) {
|
||||
return
|
||||
}
|
||||
if (el.detachEvent) {
|
||||
el.detachEvent('on' + event, handler)
|
||||
} else if (el.removeEventListener) {
|
||||
el.removeEventListener(event, handler, true)
|
||||
} else {
|
||||
el['on' + event] = null
|
||||
}
|
||||
}
|
60
frontend/src/utils/fns.js
Normal file
60
frontend/src/utils/fns.js
Normal file
@ -0,0 +1,60 @@
|
||||
export function isFunction(func) {
|
||||
return (typeof func === 'function' || Object.prototype.toString.call(func) === '[object Function]')
|
||||
}
|
||||
|
||||
// 对齐栅格
|
||||
export function snapToGrid(grid, pendingX, pendingY, scale = 1) {
|
||||
const x = Math.round((pendingX / scale) / grid[0]) * grid[0]
|
||||
const y = Math.round((pendingY / scale) / grid[1]) * grid[1]
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
// 获取rect模型
|
||||
export function getSize(el) {
|
||||
const rect = el.getBoundingClientRect()
|
||||
return [
|
||||
parseInt(rect.width),
|
||||
parseInt(rect.height)
|
||||
]
|
||||
}
|
||||
|
||||
export function computeWidth(parentWidth, left, right) {
|
||||
return parentWidth - left - right
|
||||
}
|
||||
|
||||
export function computeHeight(parentHeight, top, bottom) {
|
||||
return parentHeight - top - bottom
|
||||
}
|
||||
|
||||
export function restrictToBounds(value, min, max) {
|
||||
if (min !== null && value < min) {
|
||||
return min
|
||||
}
|
||||
|
||||
if (max !== null && max < value) {
|
||||
return max
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// 返回相对于参考点旋转后的坐标
|
||||
export function rotatedPoint(originX, originY, offsetX, offsetY, rotate) {
|
||||
const rad = (Math.PI / 180) * rotate
|
||||
const cos = Math.cos(rad)
|
||||
const sin = Math.sin(rad)
|
||||
const x = offsetX - originX
|
||||
const y = offsetY - originY
|
||||
return {
|
||||
x: x * cos - y * sin + originX,
|
||||
y: x * sin + y * cos + originY
|
||||
}
|
||||
}
|
||||
|
||||
// 根据相对坐标返回角度,正方形为顺时针
|
||||
export function getAngle(x, y) {
|
||||
let theta = Math.atan2(y, x) // 正切转弧度
|
||||
theta = Math.round((180 / Math.PI) * theta) // 弧度转角度
|
||||
if (theta < 0) theta = 360 + theta // 控制角度在0~360度
|
||||
return theta // 返回角度
|
||||
}
|
@ -7,8 +7,8 @@
|
||||
trigger="click"
|
||||
>
|
||||
<el-col>
|
||||
<el-radio v-model="panelStyleForm.gap" label="yes" @change="onChangePanelStyle">{{ $t('panel.gap') }} </el-radio>
|
||||
<el-radio v-model="panelStyleForm.gap" label="no" @change="onChangePanelStyle">{{ $t('panel.no_gap') }}</el-radio>
|
||||
<el-radio v-model="panel.gap" label="yes" @change="onChangePanelStyle">{{ $t('panel.gap') }} </el-radio>
|
||||
<el-radio v-model="panel.gap" label="no" @change="onChangePanelStyle">{{ $t('panel.no_gap') }}</el-radio>
|
||||
</el-col>
|
||||
<el-button slot="reference" size="mini" class="shape-item">{{ $t('panel.component_gap') }} <i class="el-icon-setting el-icon--right" /></el-button>
|
||||
</el-popover>
|
||||
@ -18,18 +18,32 @@
|
||||
|
||||
<script>
|
||||
import { DEFAULT_PANEL_STYLE } from '@/views/panel/panel'
|
||||
import { mapState } from 'vuex'
|
||||
import { deepCopy } from '@/components/canvas/utils/utils'
|
||||
|
||||
export default {
|
||||
name: 'BackgroundSelector',
|
||||
props: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
panelStyleForm: JSON.parse(JSON.stringify(DEFAULT_PANEL_STYLE))
|
||||
panel: null
|
||||
}
|
||||
},
|
||||
computed: mapState([
|
||||
'canvasStyleData'
|
||||
]),
|
||||
|
||||
created() {
|
||||
// 初始化赋值
|
||||
this.panel = this.canvasStyleData.panel
|
||||
},
|
||||
methods: {
|
||||
onChangePanelStyle() {
|
||||
this.$emit('onChangePanelStyle', this.panelStyleForm)
|
||||
const canvasStyleData = deepCopy(this.canvasStyleData)
|
||||
canvasStyleData.panel = this.panel
|
||||
this.$store.commit('setCanvasStyle', canvasStyleData)
|
||||
this.$store.commit('recordSnapshot')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
<el-collapse-item :title="$t('panel.panel')" name="panel">
|
||||
<el-row style="background-color: #f7f8fa; margin: 5px">
|
||||
<background-selector class="attr-selector" />
|
||||
<!-- <component-gap class="attr-selector" />-->
|
||||
<component-gap class="attr-selector" />
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('chart.module_style')" name="component">
|
||||
|
@ -74,7 +74,7 @@
|
||||
</de-aside-container>
|
||||
|
||||
<!--画布区域-->
|
||||
<de-main-container id="canvasInfo-main" style="margin-left: 5px;margin-right: 5px">
|
||||
<de-main-container id="canvasInfo-main">
|
||||
<!--左侧抽屉-->
|
||||
<el-drawer
|
||||
:visible.sync="show"
|
||||
|
Loading…
Reference in New Issue
Block a user