| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- <template>
- <div id="apps">
- <!-- 展示 -->
- <div id="openseadragon" />
- <!-- 参数调试 -->
- <div class="params">
- <n-input-group>
- <n-input-group-label>CAD宽度</n-input-group-label>
- <n-input-number
- v-model:value="Width"
- readonly
- style="width: 70%"
- />
- </n-input-group>
- <n-input-group>
- <n-input-group-label>CAD高度</n-input-group-label>
- <n-input-number
- v-model:value="Height"
- readonly
- style="width: 70%"
- />
- </n-input-group>
- <n-input-group>
- <n-input-group-label>隧道比例</n-input-group-label>
- <n-input-number
- v-model:value="scale"
- style="width: 70%"
- @update:value="initViewer"
- />
- </n-input-group>
- </div>
- <div class="text">
- <p style="font-size: 17px">
- 注:
- </p>
- <p>1. CAD宽高 = 切图宽高 * X_Y.JPG,自动计算</p>
- <p>2. 比例使用 1/比例</p>
- </div>
- </div>
- </template>
- <script setup>
- import { onMounted, ref, watchEffect } from 'vue'
- import OpenSeadragon from 'openseadragon'
- import { svgOverlay } from './js/openseadragon-svg-overlay'
- // 数据
- const scale = ref(0)
- const Width = ref(process.env.imgSize.W)
- const Height = ref(process.env.imgSize.H)
- const SIZE = process.env.imgSize.S
- let overlay = null
- let viewer = null
- const CADPATH = 'CAD_1/'
- const SVGPATH = 'tunnel/1.svg'
- const RINGWIDTH = 70
- const STARTRing = 1
- const TOTALRING = 8000
- const currentRing = 4500
- const MAXZOOM = process.env.imgSize.M
- let tunnelPath = null
- // 获取svg路径
- const getTunnelPath = () => {
- fetch(SVGPATH).then((res) => res.text()).then((txt) => {
- const objE = document.createElement('div')
- objE.innerHTML = txt
- let svg = objE.lastElementChild
- svg = document.importNode(svg, true)
- const path = svg.getElementsByTagName('path')
- // 隧道比例默认SVG宽度
- const num = +svg.getAttribute('width').replace(/[^0-9]/gi, '')
- scale.value = num
- tunnelPath = path
- initViewer()
- })
- }
- /**
- * 获取角度
- * @params x0 上一环x
- * @params y0 上一环y
- * @params x1 当前环x
- * @params y2 当前环y
- * @returns [角度,x,y]
- */
- const getDeg = (x0, y0, x1, y1) => {
- const x = (x0 + x1) / 2
- const y = (y0 + y1) / 2
- const xX = x1 - x0
- const yY = y0 - y1
- const degrees = Math.abs(
- (Math.asin(yY / Math.sqrt(yY * yY + xX * xX)) * 180) / Math.PI
- )
- let MyAngle
- if (xX >= 0 && yY >= 0) MyAngle = 270 + (90 - degrees)
- if (xX >= 0 && yY <= 0) MyAngle = degrees
- if (xX <= 0 && yY <= 0) MyAngle = 90 + (90 - degrees)
- if (xX <= 0 && yY >= 0) MyAngle = 180 + degrees
- return [ MyAngle, x, y ]
- }
- /**
- * 根据环号获取点位
- * @params sRing 开始环
- * @params eRing 结束环
- * @params path 隧道路径 默认上路径
- * @returns [{x,y}]
- */
- const getPoint = (sRing, eRing, path = tunnelPath[0]) => {
- if (!path) return []
- const StartRingPnt = [] // 通风里程点位
- const length = path.getTotalLength()
- for (let k = sRing; k < eRing; k++) {
- const Pnts = path.getPointAtLength(length * (k / TOTALRING))
- StartRingPnt.push(Pnts)
- }
- return StartRingPnt
- }
- /**
- * 画通风管道
- * @params sRing 开始环
- * @params eRing 结束环
- * @params type 类型 1 直通道 | 2 转弯通道 默认转弯通道
- * @returns dom-line
- */
- const drawLines = (sRing, eRing, type = 2, sRing2 = '22715.705078125,11780.609375', eRing2 = '23547.28515625,11636.23828125') => {
- // 通风里程点位
- const StartRingPnt = getPoint(sRing, eRing)
- // 添加通风管道=>转弯里程一定要是车行道开始里程
- const line = document.createElementNS('http://www.w3.org/2000/svg', 'polyline')
- line.setAttributeNS(null, 'fill', 'none')
- line.setAttributeNS(null, 'stroke', '#696969')
- line.setAttributeNS(null, 'stroke-width', 25)
- let txt2 = ''
- for (let k = 0; k < StartRingPnt.length; k++) {
- const el = StartRingPnt[k]
- if (type === 2) {
- if (k < StartRingPnt.length) {
- txt2 += `${el.x + RINGWIDTH / 2 - 20},${el.y + RINGWIDTH / 2 - 20} `
- } else {
- txt2 += `${el.x},${el.y} `
- }
- }
- if (type === 1) {
- txt2 += `${el.x - RINGWIDTH / 2},${el.y - RINGWIDTH / 2} `
- }
- }
- if (type === 2) txt2 += `${sRing2} ${eRing2}` // 另一个隧道开始点位
- line.setAttributeNS(null, 'transform', `translate(0 0) scale(${1 / scale.value})`)
- line.setAttributeNS(null, 'points', txt2)
- return line
- }
- /**
- * 画隧道
- * @params sRing 开始环
- * @params eRing 结束环
- * @params path 隧道路径
- * @returns obj-dom
- */
- const drawTunnel = (sRing, eRing, path = tunnelPath[0]) => {
- // 未挖段->根据开始结束区分开挖和未开挖
- const StartRingPnt = getPoint(sRing, eRing)
- const line = document.createElementNS('http://www.w3.org/2000/svg', 'polyline')
- line.setAttributeNS(null, 'fill', 'none')
- line.setAttributeNS(null, 'stroke', '#696969')
- line.setAttributeNS(null, 'stroke-width', RINGWIDTH)
- let txt = ''
- for (let k = 0; k < StartRingPnt.length; k++) {
- const el = StartRingPnt[k]
- txt += `${el.x},${el.y} `
- }
- line.setAttributeNS(null, 'transform', `translate(0 0) scale(${1 / scale.value})`)
- line.setAttributeNS(null, 'points', txt)
- // 当前环
- const cRing = sRing >= 0 ? sRing : eRing
- const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
- const length = path.getTotalLength()
- const PrePnt = path.getPointAtLength(length * ((cRing - 1) / TOTALRING))
- const Pnt = path.getPointAtLength(length * (cRing / TOTALRING))
- const deg = getDeg(PrePnt.x, PrePnt.y, Pnt.x, Pnt.y)
- const ringWidth = (1 / TOTALRING) * length * STARTRing
- rect.setAttributeNS(null, 'x', deg[1] - ringWidth / 2)
- rect.setAttributeNS(null, 'y', deg[2] - RINGWIDTH / 2)
- rect.setAttributeNS(null, 'height', RINGWIDTH)
- rect.setAttributeNS(null, 'width', ringWidth)
- rect.setAttributeNS(null, 'fill', '#87CEFA')
- rect.setAttributeNS(null, 'transform', `translate(0 0) scale(${1 / scale.value}) rotate(${deg[0]} ${deg[1]} ${deg[2]})`)
- // 点击事件
- viewer.svgOverlay().onClick(rect, (e) => {
- console.log(666, e)
- })
- return { line, rect }
- }
- /**
- * 文字
- * @params cRing 当前环
- * @params path 隧道路径
- * @returns dom-text
- */
- const drawText = (cRing, path = tunnelPath[0]) => {
- const length = path.getTotalLength()
- const PrePnt = path.getPointAtLength(length * ((cRing - 1) / TOTALRING))
- const Pnt = path.getPointAtLength(length * (cRing / TOTALRING))
- const deg = getDeg(PrePnt.x, PrePnt.y, Pnt.x, Pnt.y)
- const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
- text.innerHTML = '666666'
- text.setAttributeNS(null, 'x', Pnt.x)
- text.setAttributeNS(null, 'y', Pnt.y)
- text.setAttributeNS(null, 'fill', 'red')
- text.setAttribute('transform', `scale(${1 / scale.value}) rotate(${deg[0]} ${deg[1]} ${deg[2]}) `)
- return text
- }
- /**
- * 文字自身旋转
- * @params cRing 当前环
- * @params path 隧道路径
- * @returns dom-text
- */
- const drawText2 = (cRing, path = tunnelPath[0]) => {
- const length = path.getTotalLength()
- const Pnt = path.getPointAtLength(length * (cRing / TOTALRING))
- const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
- text.innerHTML = '555555'
- text.setAttributeNS(null, 'x', Pnt.x)
- text.setAttributeNS(null, 'y', Pnt.y)
- text.setAttributeNS(null, 'fill', 'red')
- // 测试自身旋转
- text.setAttribute('transform', `scale(${1 / scale.value}) rotate(${80} ${Pnt.x} ${Pnt.y}) `)
- return text
- }
- // 初始化
- svgOverlay(OpenSeadragon)
- const initViewer = async () => {
- if (viewer) {
- viewer.destroy()
- viewer = null
- overlay = null
- }
- // 获取CAD切图地址
- viewer = OpenSeadragon({
- id: 'openseadragon',
- showNavigationControl: true,
- showZoomControl: false,
- showHomeControl: false,
- showFullPageControl: false,
- showFlipControl: false,
- showRotationControl: false,
- zoomPerClick: 1,
- navigationControlAnchor: OpenSeadragon.ControlAnchor.TOP_LEFT,
- showNavigator: true,
- navigatorPosition: 'BOTTOM_RIGHT',
- navigatorSizeRatio: 0.125,
- minZoomLevel: 1,
- maxZoomLevel: MAXZOOM,
- defaultZoomLevel: 4,
- debugMode: false,
- visibilityRatio: 1.0,
- constrainDuringPan: false,
- tileSources: {
- height: Height.value,
- width: Width.value,
- tileSize: SIZE,
- minLevel: 9,
- maxLevel: 15,
- getTileUrl(level, x, y) {
- level -= 9
- level = 2 ** level
- // return `http://cp.caner.top:9080/public/admin/cad_config/CAD_1/${level}/${x}_${y}.jpg`
- return `${CADPATH + level}/${x}_${y}.jpg`
- }
- }
- })
- overlay = viewer.svgOverlay().node()
- // 添加隧道
- const { line, rect } = drawTunnel(currentRing, TOTALRING)
- overlay.append(line)
- overlay.append(rect)
- // 添加通风管道
- const line2 = drawLines(3798.5 - 150, 3798.5)
- overlay.append(line2)
- // 添加直通隧道
- const line3 = drawLines(150, 1500, 1)
- overlay.append(line3)
- // 添加wenz
- const txt = drawText(currentRing)
- const txt2 = drawText2(currentRing)
- overlay.append(txt)
- overlay.append(txt2)
- }
- // 生命周期
- onMounted(() => {
- document.title = '瓦片图缩放'
- getTunnelPath()
- })
- </script>
- <style lang="scss" scoped>
- #apps {
- width: 1000px;
- height: 800px;
- margin: 0 auto;
- text-align: center;
- color: #2c3e50;
- user-select: none;
- #openseadragon {
- width: 1000px;
- height: 600px;
- border: solid 1px #ccc;
- }
- .params {
- width: 100%;
- display: flex;
- margin-top: 10px;
- // justify-content: center;
- &>label {
- margin-right: 10px;
- }
- }
- .text {
- color: red;
- font-size: 13px;
- margin-top: 10px;
- text-align: left;
- &>p:not(:first-child) {
- text-indent: 20px;
- }
- }
- }
- </style>
- <style>
- .openseadragon-canvas {
- outline: none !important;
- }
- </style>
|