新增缩放

2.1
咬轮猫 4 years ago
parent 070af46c61
commit 2005fd1bdc

@ -1,12 +1,13 @@
# vue-webtopo-svgeditor # vue-webtopo-svgeditor
> vue3实现的svg可视化web组态编辑器。可无需修改代码动态添加组件 > 基于vue3实现的svg可视化web组态编辑器。可无需修改代码动态添加组件
当前主分支版本为2.0 当前主分支版本为2.1
## [版本1.0请点此](https://svgv1.yaolunmao.top) ## [版本1.0请点此](https://svgv1.yaolunmao.top)
## [图片挂了点此](https://www.cnblogs.com/Hero-/p/14784744.html) ## [图片挂了点此](https://www.cnblogs.com/Hero-/p/14784744.html)
## 预览地址 ## 预览地址
[https://svg.yaolunmao.top](https://svg.yaolunmao.top) [https://svg.yaolunmao.top](https://svg.yaolunmao.top)
@ -57,7 +58,7 @@ yarn serve
将拓展字段进行双向绑定 我目前只做了颜色 将拓展字段进行双向绑定 我目前只做了颜色
``` ```
<path :fill=\"svg_color\" :stroke=\"svg_color\" stroke-width=\"5\" style=\"pointer-events:inherit\" d=\"m143.72081869586242,163.35565803158485 c14.617751633754164,-41.93617271978648 71.89058180534832,0 0,53.91793635401125 c-71.89058180534832,-53.91793635401125 -14.617751633754164,-95.85410907379776 0,-53.91793635401125 z\" fill-opacity=\"1\" stroke-opacity=\"1\"></path> <path :fill=\"prop_data.svgColor\" :stroke=\"prop_data.svgColor\" stroke-width=\"5\" style=\"pointer-events:inherit\" d=\"m143.72081869586242,163.35565803158485 c14.617751633754164,-41.93617271978648 71.89058180534832,0 0,53.91793635401125 c-71.89058180534832,-53.91793635401125 -14.617751633754164,-95.85410907379776 0,-53.91793635401125 z\" fill-opacity=\"1\" stroke-opacity=\"1\" transform=\"translate(-145,-180)\"></path>
``` ```
修改项目文件夹pubilc下的模拟接口返回的json新增一项 修改项目文件夹pubilc下的模拟接口返回的json新增一项
@ -66,10 +67,14 @@ yarn serve
{ {
"type": "TestAddSvg", "type": "TestAddSvg",
"title": "测试新增组件", "title": "测试新增组件",
"template": "<path :fill=\"svg_color\" :stroke=\"svg_color\" stroke-width=\"5\" style=\"pointer-events:inherit\" d=\"m143.72081869586242,163.35565803158485 c14.617751633754164,-41.93617271978648 71.89058180534832,0 0,53.91793635401125 c-71.89058180534832,-53.91793635401125 -14.617751633754164,-95.85410907379776 0,-53.91793635401125 z\" fill-opacity=\"1\" stroke-opacity=\"1\"></path>", "panel_class": "draggable",
"props": ["svg_color"], "template": "<path :fill=\"prop_data.svgColor\" :stroke=\"prop_data.svgColor\" stroke-width=\"5\" style=\"pointer-events:inherit\" d=\"m143.72081869586242,163.35565803158485 c14.617751633754164,-41.93617271978648 71.89058180534832,0 0,53.91793635401125 c-71.89058180534832,-53.91793635401125 -14.617751633754164,-95.85410907379776 0,-53.91793635401125 z\" fill-opacity=\"1\" stroke-opacity=\"1\" transform=\"translate(-145,-180)\"></path>",
"default_color":"#FF0000", "props": ["prop_data"],
"priview_img":"https://svg.yaolunmao.top/test.png" "default_attr": {
"color": "#FF0000"
},
"create_type": "draggable",
"priview_img": "https://svg.yaolunmao.top/test.png"
} }
``` ```
@ -89,9 +94,14 @@ ps目前中心辅助线的坐标取决于svg组件的中心坐标请自行
## 截图 ## 截图
## ![绘制组件](https://blog-static.cnblogs.com/files/Hero-/%E7%BB%98%E5%88%B6%E7%BB%84%E4%BB%B6.gif)
![绘制图表](https://blog-static.cnblogs.com/files/Hero-/%E5%9B%BE%E8%A1%A8.gif)
![编辑器页面](https://img-blog.csdnimg.cn/20210322100014954.gif#pic_center) ![编辑器页面](https://img-blog.csdnimg.cn/20210322100014954.gif#pic_center)
![预览界面](https://img-blog.csdnimg.cn/20210322100043996.gif#pic_center) ![预览界面](https://blog-static.cnblogs.com/files/Hero-/%E9%A2%84%E8%A7%88.gif)
## License ## License

15
package-lock.json generated

@ -12380,6 +12380,21 @@
"@vue/devtools-api": "^6.0.0-beta.10" "@vue/devtools-api": "^6.0.0-beta.10"
} }
}, },
"vue-ruler-tool": {
"version": "1.2.4",
"resolved": "https://registry.npm.taobao.org/vue-ruler-tool/download/vue-ruler-tool-1.2.4.tgz",
"integrity": "sha1-MQTjS2UO2nHJpHWXb4yyjGTNEKc=",
"requires": {
"vue": "^2.5.11"
},
"dependencies": {
"vue": {
"version": "2.6.14",
"resolved": "https://registry.nlark.com/vue/download/vue-2.6.14.tgz",
"integrity": "sha1-5RqlJQJQ1Wmj+606ilpofWA24jU="
}
}
},
"vue-style-loader": { "vue-style-loader": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npm.taobao.org/vue-style-loader/download/vue-style-loader-4.1.3.tgz", "resolved": "https://registry.npm.taobao.org/vue-style-loader/download/vue-style-loader-4.1.3.tgz",

@ -1,8 +1,8 @@
<template> <template>
<div class="components-layout-left"> <div class="components-layout-left leftNav">
<a-input-search placeholder="搜索组件" /> <!-- <a-input-search placeholder="搜索组件" /> -->
<a-collapse v-model:activeKey="activeKey" <a-collapse v-model:activeKey="activeKey"
accordion> accordion>
<a-collapse-panel key="1" <a-collapse-panel key="1"
@ -99,7 +99,7 @@ export default {
} }
}; };
</script> </script>
<style> <style lang="less" scoped>
.components-layout-left .ant-input-search-icon { .components-layout-left .ant-input-search-icon {
font-size: 20px !important; font-size: 20px !important;
color: #1890ff !important; color: #1890ff !important;
@ -112,8 +112,6 @@ export default {
.components-layout-left .ant-collapse-content > .ant-collapse-content-box { .components-layout-left .ant-collapse-content > .ant-collapse-content-box {
padding: 16px 0; padding: 16px 0;
} }
</style>
<style lang="less" scoped>
.ant-input-affix-wrapper { .ant-input-affix-wrapper {
height: 45px; height: 45px;
line-height: 45px; line-height: 45px;
@ -129,7 +127,6 @@ export default {
li { li {
position: relative; position: relative;
width: calc(33.33% - 30px); width: calc(33.33% - 30px);
height: 56px;
margin: 0 15px 15px 15px; margin: 0 15px 15px 15px;
padding: 0; padding: 0;
border-radius: 50%; border-radius: 50%;
@ -140,7 +137,7 @@ export default {
cursor: pointer; cursor: pointer;
&:hover { &:hover {
box-shadow: 1px 1px 5px #0090ff; box-shadow: 1px 1px 10px #ccc;
} }
img { img {
@ -180,4 +177,15 @@ export default {
.toolbar-selected { .toolbar-selected {
outline: 1px solid #0cf; outline: 1px solid #0cf;
} }
.leftNav {
position: absolute;
left: 0;
top: 0;
bottom: 0;
min-width: unset !important;
max-width: unset !important;
width: 260px !important;
z-index: 1;
overflow: auto;
}
</style> </style>

@ -1,7 +1,11 @@
<!--
* @Author: yaolunmao
-->
<template> <template>
<div class="rightNav">
<a-tabs type="card" class="components-layout-right"> <a-tabs type="card" class="components-layout-right">
<a-tab-pane key="1" tab="外观"> <a-tab-pane key="1" tab="外观">
<a-form layout="horizontal"> <a-form layout="horizontal" :label-col="{ span: 6 }" :wrapper-col="{ span: 10 }" labelAlign="left">
<a-form-item label="id"> <a-form-item label="id">
<p>{{svgInfo.id}}</p> <p>{{svgInfo.id}}</p>
</a-form-item> </a-form-item>
@ -37,7 +41,7 @@
<div class="bg-code">{{selectSvgInfo}}</div> <div class="bg-code">{{selectSvgInfo}}</div>
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
</div>
</template> </template>
<script> <script>
export default { export default {
@ -57,7 +61,7 @@ export default {
} }
}; };
</script> </script>
<style lang="less"> <style scoped lang="less">
.components-layout-right{ .components-layout-right{
.ant-tabs-bar{ .ant-tabs-bar{
margin-bottom: 0 !important; margin-bottom: 0 !important;
@ -97,7 +101,6 @@ export default {
right: 15px; right: 15px;
bottom: 0; bottom: 0;
height: 1px; height: 1px;
background: #f2f2f2;
} }
&:last-child::after{ &:last-child::after{
@ -105,8 +108,6 @@ export default {
} }
} }
} }
</style>
<style scoped lang="less">
.btn-sure{ .btn-sure{
width: 260px; width: 260px;
margin: 20px; margin: 20px;
@ -119,4 +120,15 @@ export default {
border-radius: 4px; border-radius: 4px;
padding: 10px; padding: 10px;
} }
.rightNav {
right: 0;
top: 0;
bottom: 0;
min-width: unset !important;
max-width: unset !important;
width: 300px !important;
z-index: 1;
overflow: auto;
padding:10px 20px;
}
</style> </style>

@ -36,6 +36,7 @@
@ok="versionModelHandleOk"> @ok="versionModelHandleOk">
<p>新增绘制组件</p> <p>新增绘制组件</p>
<p>新增图表</p> <p>新增图表</p>
<p>新增缩放功能</p>
<p>新增模板-加载模板后点击预览-点击模拟硬件-等待两秒查看效果</p> <p>新增模板-加载模板后点击预览-点击模拟硬件-等待两秒查看效果</p>
<p>如果图片加载不出来请清空缓存刷新(F12右键刷新按钮-选择清空缓存并进行硬刷新)</p> <p>如果图片加载不出来请清空缓存刷新(F12右键刷新按钮-选择清空缓存并进行硬刷新)</p>
</a-modal> </a-modal>
@ -46,11 +47,12 @@
@click="testE">载入模板</a-button> --> @click="testE">载入模板</a-button> -->
<a-button type="danger" <a-button type="danger"
@click="versionModelVisible=true">当前为2.1版本</a-button> @click="versionModelVisible=true"
style="margin-left:20px">当前为2.1版本</a-button>
<a-button type="primary" <a-button type="primary"
@click="testA" @click="testA"
style="margin-left:20px">载入模板</a-button> style="margin-left:120px">载入模板</a-button>
<a-button type="primary" <a-button type="primary"
@click="testH" @click="testH"
style="margin-left:20px">预览</a-button> style="margin-left:20px">预览</a-button>
@ -88,19 +90,16 @@
@click="exportData">导出数据</a-button> @click="exportData">导出数据</a-button>
</a> </a>
</a-layout-header> </a-layout-header>
<span v-if="!shrink"
@click="exitFullscreen"
class="icon-shrink svgfont">&#xe62b;</span>
<a-layout class="pageMain"> <a-layout class="pageMain">
<a-layout-sider class="leftNav"> <!-- <a-layout> -->
<a-layout-sider width="260px">
<LeftToolBar :svgInfoData=svgInfoData></LeftToolBar> <LeftToolBar :svgInfoData=svgInfoData></LeftToolBar>
</a-layout-sider> </a-layout-sider>
<a-layout-content <a-layout-content class="centerContain">
:class="{ fixed: !shrink }"
style="transform: scale(1)">
<div class="canvas-content"
ref="canvas"
<div ref="canvas"
class="canvansDiv"
:style="'transform: scale('+scaleValue+')'"
@mousemove="MouseMove" @mousemove="MouseMove"
@mousedown="MousedownCanvas" @mousedown="MousedownCanvas"
@mouseup="MouseupCanvas" @mouseup="MouseupCanvas"
@ -108,9 +107,11 @@
@mousewheel="MouseWheel"> @mousewheel="MouseWheel">
<!--拖动辅助线--> <!--拖动辅助线-->
<div id="guide-x" <div id="guide-x"
ref="guidex_dom"></div> ref="guidex_dom"
:style="'border-top: '+1/scaleValue+'px dashed #55f'"></div>
<div id="guide-y" <div id="guide-y"
ref="guidey_dom"></div> ref="guidey_dom"
:style="'border-left: '+1/scaleValue+'px dashed #55f'"></div>
<!-- 画布 --> <!-- 画布 -->
<svg version="1.1" <svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -141,8 +142,18 @@
</g> </g>
</svg> </svg>
</div> </div>
<div class="zoonStyle">
<div style="text-color:black">缩放
<a-slider :default-value="1"
:min="0.1"
:max="2"
:step="0.1"
@change="scaleValueChange"
style="width:200px" />
</div>
</div>
</a-layout-content> </a-layout-content>
<a-layout-sider class="rightNav"> <a-layout-sider width="300px">
<RightToolBar :svgInfo=selectSvgInfo <RightToolBar :svgInfo=selectSvgInfo
@setTableAttr="setTableAttr"></RightToolBar> @setTableAttr="setTableAttr"></RightToolBar>
</a-layout-sider> </a-layout-sider>
@ -154,7 +165,6 @@
<script> <script>
import LeftToolBar from '@/components/LeftToolBar.vue'; import LeftToolBar from '@/components/LeftToolBar.vue';
import RightToolBar from '@/components/RightToolBar.vue'; import RightToolBar from '@/components/RightToolBar.vue';
// import SvgComponents from '@/components/SvgComponents.vue';
import SvgComponents from '@/components/SvgComponents.vue'; import SvgComponents from '@/components/SvgComponents.vue';
export default { export default {
components: { LeftToolBar, RightToolBar, SvgComponents }, components: { LeftToolBar, RightToolBar, SvgComponents },
@ -194,9 +204,7 @@ export default {
mouseStatus: 0, // 1 0 mouseStatus: 0, // 1 0
selectSvgInfo: '', selectSvgInfo: '',
clickType: '',// clickType: '',//
tableRowCount: 2,// scaleValue: 1,//
tableColCount: 2,//
tableDefaultData: []
} }
}, },
methods: { methods: {
@ -239,7 +247,7 @@ export default {
return; return;
} }
const { clientX, clientY } = e const { clientX, clientY } = e
// console.log(e.offsetX,e.offsetY);
// let svgID = this.svgLists[this.selectSvg.Index].id; // let svgID = this.svgLists[this.selectSvg.Index].id;
let svgID = this.selectSvg.ID; let svgID = this.selectSvg.ID;
//svg //svg
@ -249,8 +257,8 @@ export default {
// //
let svgPositionX = this.selectSvg.pointX; let svgPositionX = this.selectSvg.pointX;
let svgPositionY = this.selectSvg.pointY; let svgPositionY = this.selectSvg.pointY;
svgPositionX += (clientX - this.selectSvg.mPositionX); svgPositionX += (clientX - this.selectSvg.mPositionX) / this.scaleValue;
svgPositionY += (clientY - this.selectSvg.mPositionY); svgPositionY += (clientY - this.selectSvg.mPositionY) / this.scaleValue;
setTimeout(function () { setTimeout(function () {
// //
//x10 //x10
@ -274,7 +282,7 @@ export default {
return list.svgPositionX === svgPositionX return list.svgPositionX === svgPositionX
}); });
if (exitsNowX.length > 0) { if (exitsNowX.length > 0) {
_this.$refs.guidey_dom.style.setProperty('left', svgPositionX - 1 + 'px'); _this.$refs.guidey_dom.style.setProperty('left', svgPositionX - 1 / _this.scaleValue + 'px');
_this.$refs.guidey_dom.style.display = 'inline'; _this.$refs.guidey_dom.style.display = 'inline';
} }
else { else {
@ -285,7 +293,7 @@ export default {
return list.svgPositionY === svgPositionY return list.svgPositionY === svgPositionY
}); });
if (exitsNowY.length > 0) { if (exitsNowY.length > 0) {
_this.$refs.guidex_dom.style.setProperty('top', svgPositionY + 'px'); _this.$refs.guidex_dom.style.setProperty('top', svgPositionY - 1 / _this.scaleValue + 'px');
_this.$refs.guidex_dom.style.display = 'inline'; _this.$refs.guidex_dom.style.display = 'inline';
} }
else { else {
@ -448,6 +456,9 @@ export default {
tableData.push(tableRowData) tableData.push(tableRowData)
} }
this.svgLists[tableIndex].tableData = tableData; this.svgLists[tableIndex].tableData = tableData;
},
scaleValueChange (newValue) {
this.scaleValue = newValue;
} }
}, },
mounted () { mounted () {
@ -576,19 +587,8 @@ export default {
bottom: 0; bottom: 0;
overflow: auto; overflow: auto;
} }
.leftNav {
position: absolute;
left: 0;
top: 0;
bottom: 0;
min-width: unset !important;
max-width: unset !important;
width: 260px !important;
z-index: 1;
overflow: auto;
}
.centerContain { .centerContain {
position: absolute; // position: absolute;
left: 260px; left: 260px;
right: 300px; right: 300px;
top: 0; top: 0;
@ -606,7 +606,16 @@ export default {
top: 0; top: 0;
bottom: 0; bottom: 0;
} }
.canvansDiv {
width: 1920px;
height: 1080px;
transform-origin: left top;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}
.canvas-content { .canvas-content {
width: 1920px; width: 1920px;
height: 1080px; height: 1080px;
@ -626,33 +635,6 @@ export default {
} }
} }
} }
.rightNav {
position: absolute;
right: 0;
top: 0;
bottom: 0;
min-width: unset !important;
max-width: unset !important;
width: 300px !important;
z-index: 1;
overflow: auto;
}
.icon-shrink {
position: fixed;
right: 20px;
top: 5px;
font-size: 24px;
color: #fff;
cursor: pointer;
background: #1890ff;
width: 38px;
height: 38px;
line-height: 38px;
text-align: center;
border-radius: 50%;
user-select: none;
z-index: 1111;
}
#components-layout .ant-layout-sider { #components-layout .ant-layout-sider {
background: #fff; background: #fff;
@ -661,18 +643,16 @@ export default {
#guide-x { #guide-x {
display: none; display: none;
position: absolute; position: absolute;
border-top: 1px dashed #55f;
width: 100%; width: 100%;
left: 0px; left: 0px;
top: 500px; top: 0px;
} }
#guide-y { #guide-y {
display: none; display: none;
position: absolute; position: absolute;
border-left: 1px dashed #55f;
height: 100%; height: 100%;
left: 100px; left: 0px;
top: 0px; top: 0px;
} }
.ant-slider { .ant-slider {
@ -751,4 +731,11 @@ export default {
.topo-layer-view-selected { .topo-layer-view-selected {
outline: 1px solid #0cf; outline: 1px solid #0cf;
} }
.zoonStyle {
position: fixed;
bottom: 4px;
z-index: 99;
color: #fff;
background: #000;
}
</style> </style>

Loading…
Cancel
Save