import Dialog from '../../Obj/Element/Dialog'; import Tools from '../../Tools'; import { legp } from '../../Obj/Element/datalist' import { getTemplateData } from './dataSource.js' let tools = new Tools(); async function MapPrint(sdk, thumbnailImg, rectangle, originalImg) { let exporting = false; let templateData = getTemplateData(tools) let _DialogObject let template = '1' let unitDistance let isLoad = true let borderImage let margin = 0 let svgText let title = { text: '标题', height: 40, bgColor: '#5d5d5d', color: '#ffffff', show: true, } let border = { show: true, url: tools.getSourceRootPath() + '/custom/img/map-border1.svg', width: 20, } let data = [ { text: '', x: 10, y: 100, height: 24, fontSize: 24, isSelected: false, show: true, color: '#ffffff', }, { text: '-', x: 10, y: 100, height: 24, fontSize: 24, isSelected: false, show: true, color: '#ffffff', }, { x: 10, y: 100, width: 100, height: 100, show: false, isSelected: false, url: tools.getSourceRootPath() + '/custom/img/icon-compass1.svg' } ] // 比例尺 let plottingScale = { cell: 2, color: '#ffffff', show: true, isSelected: false, x: 10, y: 100, width: 100, } let compassList = [ '/custom/img/icon-compass1.svg', '/custom/img/icon-compass2.svg', '/custom/img/icon-compass3.svg', '/custom/img/icon-compass4.svg' ] if (_DialogObject) { _DialogObject.close() _DialogObject = null } _DialogObject = await new Dialog(sdk, {}, { title: '地图打印', left: '5%', top: '10%', ismove: false }) _DialogObject._element.body.className = _DialogObject._element.body.className + ' map-print' let contentElm = document.createElement('div'); contentElm.innerHTML = `
图件信息
模板
标题
制图日期
制图单位
图框
地图要素
指北针
${(() => { let str = ''; for (let i = 0; i < compassList.length; i++) { const compass = tools.getSourceRootPath() + compassList[i]; str += `
` } return str })()}
比例尺
`; _DialogObject.contentAppChild(contentElm) let leftElm = contentElm.getElementsByClassName('left')[0] let rightElm = contentElm.getElementsByClassName('right')[0] // let mapImgBoxElm = rightElm.getElementsByClassName('map-img-box')[0] let titleInputElm = leftElm.getElementsByClassName('title-input')[0] let titleCheckboxElm = leftElm.getElementsByClassName('title-checkbox')[0] let unitInputElm = leftElm.getElementsByClassName('unit-input')[0] let unitCheckboxElm = leftElm.getElementsByClassName('unit-checkbox')[0] let compassCheckboxElm = leftElm.getElementsByClassName('compass-checkbox')[0] let compassRadiosElm = leftElm.getElementsByClassName('compass-radio') let plottingScaleCheckboxElm = leftElm.getElementsByClassName('plotting-scale-checkbox')[0] let mapBorderCheckboxElm = leftElm.getElementsByClassName('map-border-checkbox')[0] let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); rightElm.appendChild(canvas) let imgElm = new Image(); imgElm.src = thumbnailImg imgElm.onload = function () { isLoad = false getPlottingScale() changeTemplate(template) } // 标题 titleInputElm.value = title.text; titleCheckboxElm.checked = title.show; titleInputElm.addEventListener('input', function () { title.text = this.value; if (imgElm.complete) { updateCanvas() } }); titleCheckboxElm.addEventListener('change', function () { title.show = this.checked; if (imgElm.complete) { updateCanvas() } }); // 制图单位 unitInputElm.value = data[1].text; unitCheckboxElm.checked = data[1].show; unitInputElm.addEventListener('input', function () { data[1].text = this.value; if (imgElm && imgElm.complete) { updateCanvas() } }); unitCheckboxElm.addEventListener('change', function () { data[1].show = this.checked; if (imgElm && imgElm.complete) { updateCanvas() } }) // 指北针 compassCheckboxElm.checked = data[2].show; compassCheckboxElm.addEventListener('change', function () { data[2].show = this.checked; if (imgElm && imgElm.complete) { updateCanvas() } }) for (let i = 0; i < compassRadiosElm.length; i++) { compassRadiosElm[i].addEventListener('change', function () { if (this.checked) { data[2].svg = null data[2].url = compassList[i] if (imgElm && imgElm.complete) { updateCanvas() } } }) } // 比例尺 plottingScaleCheckboxElm.checked = plottingScale.show; plottingScaleCheckboxElm.addEventListener('change', function () { plottingScale.show = this.checked; if (imgElm && imgElm.complete) { updateCanvas() } }) // 图框 mapBorderCheckboxElm.checked = border.show; mapBorderCheckboxElm.addEventListener('change', function () { border.show = this.checked; if (borderImage && borderImage.complete) { updateCanvas() } }) let borderColorPicker = new YJColorPicker({ el: contentElm.getElementsByClassName('border-color')[0], size: 'mini', //颜色box类型 alpha: false, //是否开启透明度 defaultColor: border.color, disabled: false, //是否禁止打开颜色选择器 openPickerAni: 'opacity', //打开颜色选择器动画 sure: color => { changeMapBorderColor(color) }, //点击确认按钮事件回调 clear: () => { changeMapBorderColor('rgba(0,0,0,1)') } //点击清空按钮事件回调 }) let jeDateObject let printDateCheckboxElm let mapBorderDataLegpElm let mapBorderObject let iActiveElm let closeBtn let exportBtn setTimeout(() => { closeBtn = _DialogObject._element.foot.getElementsByClassName('close')[0] exportBtn = document.createElement('button') exportBtn.className = 'export'; exportBtn.innerHTML = '打印'; leftElm.appendChild(closeBtn) leftElm.appendChild(exportBtn) exportBtn.addEventListener('click', function () { if (exporting) { return } exporting = true exportBtn.innerHTML = '打印' exportMap() // exporting = true // exportBtn.innerHTML = '打印' // let imgBlobData = canvas.toDataURL(); // let downloadElement = document.createElement('a'); // downloadElement.href = imgBlobData; // downloadElement.download = `高清出图-${getDateTimeString()}.png`; // document.body.appendChild(downloadElement); // downloadElement.click(); // document.body.removeChild(downloadElement); // URL.revokeObjectURL(imgBlobData); }) // 时间 let printDateElm = contentElm.getElementsByClassName('print-date')[0] printDateCheckboxElm = contentElm.getElementsByClassName('print-date-checkbox')[0] printDateCheckboxElm.checked = data[0].show; printDateCheckboxElm.addEventListener('change', function () { data[0].show = this.checked; if (imgElm.complete) { updateCanvas() } }) jeDateObject = jeDate(printDateElm, { format: "YYYY-MM-DD", isinitVal: true, isClear: false, donefun: function (obj) { data[0].text = obj.val; if (imgElm.complete) { updateCanvas() } } }); if (data[0].text) { jeDateObject.setValue(data[0].text) } else { jeDateObject.nowBtn && jeDateObject.nowBtn() data[0].text = jeDateObject.getValue() updateCanvas() } // 模板 // let templateData = templateData let templateObject = legp( _DialogObject._element.content.getElementsByClassName( 'template-box' )[0], '.template' ) if (templateObject) { templateObject.legp_search(templateData) let templateDataLegpElm = _DialogObject._element.content .getElementsByClassName('template')[0] .getElementsByTagName('input')[0] for (let i = 0; i < templateData.length; i++) { if (templateData[i].id == template) { templateDataLegpElm.value = templateData[i].value templateObject.legp_searchActive( templateData[i].value ) break } } templateDataLegpElm.addEventListener('input', () => { for (let i = 0; i < templateData.length; i++) { if (templateData[i].value === templateDataLegpElm.value) { changeTemplate(templateData[i].id) break } } }) } // 图框 let mapBorderData = [ { name: ``, value: '/custom/img/map-border1.svg', key: 0, }, { name: ``, value: '/custom/img/map-border2.svg', key: 1, }, { name: ``, value: '/custom/img/map-border3.svg', key: 2, }, { name: ``, value: '/custom/img/map-border4.svg', key: 3, }, { name: ``, value: '/custom/img/map-border5.svg', key: 4, }, { name: ``, value: '/custom/img/map-border6.svg', key: 5, }, ] mapBorderObject = legp( _DialogObject._element.content.getElementsByClassName( 'map-border-box' )[0], '.map-border' ) if (mapBorderObject) { mapBorderObject.legp_search(mapBorderData) iActiveElm = document.createElement('span') iActiveElm.className = "icon icon-active" iActiveElm.style.width = 'calc(100% - 40px)' iActiveElm.style.height = 'calc(100% - 12px)' iActiveElm.style.position = 'absolute' iActiveElm.style.top = '6px' iActiveElm.style.left = '10px' iActiveElm.style.pointerEvents = 'none' iActiveElm.style.backgroundImage = `url(${tools.getSourceRootPath() + border.url})` iActiveElm.style.backgroundSize = 'auto 100%' iActiveElm.style.backgroundRepeat = 'repeat-x' _DialogObject._element.content .getElementsByClassName('map-border')[0].getElementsByClassName('cy_datalist')[0].appendChild(iActiveElm) mapBorderDataLegpElm = _DialogObject._element.content .getElementsByClassName('map-border')[0] .getElementsByTagName('input')[0] mapBorderDataLegpElm.style.fontSize = 0 mapBorderDataLegpElm.style.color = 'transparent' for (let i = 0; i < mapBorderData.length; i++) { if (mapBorderData[i].value == border.url) { mapBorderDataLegpElm.value = mapBorderData[i].value mapBorderObject.legp_searchActive( mapBorderData[i].value ) break } } mapBorderDataLegpElm.addEventListener('input', () => { for (let i = 0; i < mapBorderData.length; i++) { if (mapBorderData[i].value === mapBorderDataLegpElm.value) { iActiveElm.style.backgroundImage = `url(${tools.getSourceRootPath() + mapBorderData[i].value})` changeMapBorder(mapBorderData[i].value) break } } }) } }, 0); function initData() { if (isLoad) { return } margin = margin * imgElm.width triggerRange = imgElm.height / 140; titleInputElm.value = title.text; titleCheckboxElm.checked = title.show; unitInputElm.value = data[1].text; unitCheckboxElm.checked = data[1].show; compassCheckboxElm.checked = data[2].show; for (let i = 0; i < compassList.length; i++) { if (compassList[i] === data[2].url) { compassRadiosElm[i].checked = true } } plottingScaleCheckboxElm.checked = plottingScale.show; border.width = imgElm.width * border.width let allmargin = margin if (border.show && borderImage && borderImage.complete) { allmargin = allmargin + border.width } canvas.width = imgElm.width + (allmargin * 2) canvas.height = imgElm.height + (allmargin * 2) printDateCheckboxElm && (printDateCheckboxElm.checked = data[0].show); if (jeDateObject) { if (data[0].text) { jeDateObject.setValue(data[0].text) } else { jeDateObject.nowBtn && jeDateObject.nowBtn() data[0].text = jeDateObject.getValue() } } // plottingScale.x = imgElm.width * plottingScale.x; // plottingScale.y = imgElm.height * plottingScale.y; if (mapBorderObject && mapBorderDataLegpElm && iActiveElm) { mapBorderDataLegpElm.value = border.url; mapBorderObject.legp_searchActive( border.url ) iActiveElm.style.backgroundImage = `url(${tools.getSourceRootPath() + border.url})` } mapBorderCheckboxElm.checked = border.show; borderImage = null if (border && border.url) { changeMapBorder(border.url) } } function changeTemplate(v) { template = v templateData = getTemplateData(tools) for (let i = 0; i < templateData.length; i++) { if (templateData[i].id === template) { title = templateData[i].title || title margin = ((!templateData[i].margin && templateData[i].margin != 0) ? margin : templateData[i].margin) data = templateData[i].data || data border = templateData[i].border || border border.color = border.color || '#000000' plottingScale = templateData[i].plottingScale || plottingScale break } } initData() updateCanvas() } function changeMapBorder(v) { border.url = v if (!border.url) { return } borderImage = new Image(); borderImage.setAttribute('crossOrigin', 'anonymous'); if (border.url.endsWith('svg')) { fetch(tools.getSourceRootPath() + border.url).then(async (response) => { if (response.ok) { svgText = await response.text(); changeMapBorderColor(border.color) } }) } else { borderImage.src = tools.getSourceRootPath() + border.url; borderImage.onload = () => { if (border.show) { updateCanvas(); } } } } function changeMapBorderColor(color) { border.color = color || '#000000' new YJColorPicker({ el: contentElm.getElementsByClassName('border-color')[0], size: 'mini', //颜色box类型 alpha: false, //是否开启透明度 defaultColor: border.color, disabled: false, //是否禁止打开颜色选择器 openPickerAni: 'opacity', //打开颜色选择器动画 sure: color => { changeMapBorderColor(color) }, //点击确认按钮事件回调 clear: () => { changeMapBorderColor('rgba(0,0,0,1)') } //点击清空按钮事件回调 }) let currentSvg let svgDataUrl if (color) { const colorRegex = /fill="[^"]+"/g; currentSvg = svgText.replace(colorRegex, `fill="${color}"`); } else { currentSvg = svgText } svgDataUrl = 'data:image/svg+xml;base64,' + btoa(Array.from(new TextEncoder().encode(currentSvg), (byte) => String.fromCharCode(byte)).join('')); borderImage = new Image(); borderImage.setAttribute('crossOrigin', 'anonymous'); borderImage.src = svgDataUrl; borderImage.onload = () => { if (border.show) { updateCanvas(); } } } let isDragging = false; let triggerRange = 5; let selectedElement = null; let isDraggingElement = false; let isResizingElement = false; let resizeCorner = null; let startX, startY, startY2, startX2; let elementOffsetX, elementOffsetY; let elementWidth, elementHeight; let currentFontSize; // 记录当前字体大小 function getCanvasMouseY(e) { const rect = canvas.getBoundingClientRect(); const containerWidth = rect.width; const containerHeight = rect.height; const canvasWidth = canvas.width; const canvasHeight = canvas.height; let scale; if (canvasWidth / canvasHeight > containerWidth / containerHeight) { scale = containerWidth / canvasWidth; } else { scale = containerHeight / canvasHeight; } const scaledWidth = canvasWidth * scale; const scaledHeight = canvasHeight * scale; const offsetX = (containerWidth - scaledWidth) / 2; const offsetY = (containerHeight - scaledHeight) / 2; const clientY = e.clientY - rect.top - offsetY; return clientY / scale; } function getCanvasMouseX(e) { const rect = canvas.getBoundingClientRect(); const containerWidth = rect.width; const containerHeight = rect.height; const canvasWidth = canvas.width; const canvasHeight = canvas.height; let scale; if (canvasWidth / canvasHeight > containerWidth / containerHeight) { scale = containerWidth / canvasWidth; } else { scale = containerHeight / canvasHeight; } const scaledWidth = canvasWidth * scale; const scaledHeight = canvasHeight * scale; const offsetX = (containerWidth - scaledWidth) / 2; const offsetY = (containerHeight - scaledHeight) / 2; const clientX = e.clientX - rect.left - offsetX; return clientX / scale; } function getCorners(element, allmargin) { let elementX = element.x * imgElm.width + allmargin; let elementY = element.y * imgElm.height + allmargin; let elementWidth = element.width * imgElm.height; let elementHeight = element.height * imgElm.height; if ('text' in element) { return [ { x: elementX, y: elementY - elementHeight }, { x: elementX + elementWidth, y: elementY - elementHeight }, { x: elementX, y: elementY }, { x: elementX + elementWidth, y: elementY } ]; } else if ('url' in element) { return [ { x: elementX, y: elementY }, { x: elementX + elementWidth, y: elementY }, { x: elementX, y: elementY + elementHeight }, { x: elementX + elementWidth, y: elementY + elementHeight } ]; } else { // 比例尺 return [ { x: elementX, y: elementY }, { x: elementX + elementWidth, y: elementY }, { x: elementX, y: elementY + elementHeight }, { x: elementX + elementWidth, y: elementY + elementHeight } ] } } function updateCanvas() { if (isLoad) { return } let allmargin = margin if (border.show && borderImage && borderImage.complete) { allmargin = allmargin + border.width } canvas.width = imgElm.width + (allmargin * 2) canvas.height = imgElm.height + (allmargin * 2) ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.rect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "#ffffff"; ctx.fill(); ctx.drawImage(imgElm, allmargin, allmargin, imgElm.width, imgElm.height); // 标题内容 if (title.show) { const text = title.text; const fontSize = Math.max(5, (title.height * imgElm.height) * 0.5); ctx.font = `${fontSize}px serif`; // const textWidth = ctx.measureText(text).width; ctx.fillStyle = title.bgColor || '#5d5d5d'; ctx.fillRect(allmargin, allmargin, canvas.width - (allmargin * 2), (title.height * imgElm.height)); ctx.fillStyle = title.color || 'white'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(text, canvas.width / 2, ((title.height * imgElm.height) / 2) + allmargin); } // 其他内容 for (let i = 0; i < data.length; i++) { if (data[i].show) { if ('text' in data[i]) { ctx.font = `${imgElm.height * data[i].height}px serif`; ctx.fillStyle = data[i].color || 'white'; ctx.textAlign = 'left'; ctx.textBaseline = 'bottom'; data[i].width = ctx.measureText(data[i].text).width / imgElm.height; ctx.fillText(data[i].text, (imgElm.width * data[i].x) + allmargin, (imgElm.height * data[i].y) + allmargin); if (data[i].isSelected) { drawSelectionBorder(data[i]); } } else if ('url' in data[i]) { if (data[i].svg && data[i].svg.complete) { ctx.drawImage(data[i].svg, (imgElm.width * data[i].x) + allmargin, (imgElm.height * data[i].y) + allmargin, imgElm.height * data[i].width, imgElm.height * data[i].height); if (data[i].isSelected) { drawSelectionBorder(data[i]); } } else { const svg = new Image(); svg.src = tools.getSourceRootPath() + data[i].url; svg.onload = function () { data[i].svg = svg ctx.drawImage(svg, (imgElm.width * data[i].x) + allmargin, (imgElm.height * data[i].y) + allmargin, imgElm.height * data[i].width, imgElm.height * data[i].height); if (data[i].isSelected) { drawSelectionBorder(data[i]); } } } } } } // 比例尺 if (plottingScale.show) { let allmargin = margin if (border.show && borderImage && borderImage.complete) { allmargin = allmargin + border.width } let plottingScaleX = imgElm.width * plottingScale.x + allmargin let plottingScaleY = imgElm.height * plottingScale.y + allmargin let unit = 'm' // const fontSize = plottingScale.width * 0.12; const fontSize = imgElm.width * 0.08 * 0.12; let spacing = imgElm.width * 0.08 / plottingScale.cell; let spacingDistance = Math.round(unitDistance * spacing); let spacingDistanceString = spacingDistance + '' if (spacingDistance < 10) { } else { spacingDistance = Number(spacingDistanceString[0]) for (let i = 0; i < spacingDistanceString.length - 1; i++) { spacingDistance = spacingDistance * 10 } spacing = spacingDistance / unitDistance } plottingScale.width = spacing * plottingScale.cell; plottingScale.height = plottingScale.width * 0.2; if (spacingDistance >= 1000) { unit = '㎞' spacingDistance = Math.round(spacingDistance / 1000); } const scaleY = plottingScaleY; ctx.beginPath(); ctx.moveTo(plottingScaleX, scaleY); ctx.lineTo(plottingScaleX + plottingScale.width, scaleY); ctx.strokeStyle = plottingScale.color; ctx.lineWidth = plottingScale.width * 0.01; ctx.stroke(); let tickX = 0 for (let i = 0; i <= plottingScale.cell; i++) { tickX = plottingScaleX + i * spacing; ctx.beginPath(); ctx.moveTo(tickX, scaleY - plottingScale.width * 0.1); ctx.lineTo(tickX, scaleY); ctx.strokeStyle = plottingScale.color; ctx.lineWidth = plottingScale.width * 0.01; ctx.stroke(); ctx.font = `${fontSize}px Arial`; ctx.fillStyle = plottingScale.color; ctx.textAlign = 'center'; ctx.textBaseline = 'bottom'; ctx.fillText(i * spacingDistance, tickX, scaleY - plottingScale.width * 0.1); } ctx.font = `${fontSize}px Arial`; ctx.fillStyle = plottingScale.color; ctx.textAlign = 'left'; ctx.textBaseline = 'bottom'; ctx.fillText(unit, tickX + (fontSize * 1.2), scaleY - plottingScale.width * 0.1); if (plottingScale.isSelected) { drawSelectionBorder(plottingScale); } } // 边框 if (border.show && borderImage && borderImage.complete) { // 绘制四个角(裁剪成45度角) drawBorder(ctx, borderImage, margin, margin, border.width, 'top', 1); drawBorder(ctx, borderImage, canvas.width - border.width - margin, margin, border.width, 'right', 1); drawBorder(ctx, borderImage, canvas.width - border.width - margin, canvas.height - border.width - margin, border.width, 'bottom', 1); drawBorder(ctx, borderImage, margin, canvas.height - border.width - margin, border.width, 'left', 1); } } // 绘制边框 function drawBorder(ctx, img, x, y, size, position, isStart = 1) { ctx.save(); ctx.translate(x + size / 2, y + size / 2); // 根据位置设置旋转角度 switch (position) { case 'right': ctx.rotate(Math.PI / 2); break; case 'bottom': ctx.rotate(Math.PI); break; case 'left': ctx.rotate(3 * Math.PI / 2); break; } // 创建45度角的裁剪路径 ctx.beginPath(); ctx.moveTo((-size * isStart) / 2, -size / 2); if (position === 'top' || position === 'bottom') { ctx.lineTo(canvas.width - (margin * 2) - (size / 2), -size / 2); ctx.lineTo(canvas.width - (margin + size) * 2 + (size / 2), size / 2); } else { ctx.lineTo(canvas.height - (margin * 2) - (size / 2), -size / 2); ctx.lineTo(canvas.height - (margin + size) * 2 + (size / 2), size / 2); } ctx.lineTo((size * isStart) / 2, size / 2); ctx.closePath(); ctx.clip(); let imgWidth = img.width / img.height * size // 绘制图片 ctx.drawImage(img, -size / 2, -size / 2, imgWidth, size); let count; if (position === 'top' || position === 'bottom') { count = Math.ceil((canvas.width - (margin * 2) - (border.width * 2)) / border.width); } else { count = Math.ceil((canvas.height - (margin * 2) - (border.width * 2)) / border.width); } count++ for (let i = 1; i <= count; i++) { ctx.drawImage(img, -size / 2 + imgWidth * i, -size / 2, imgWidth, size); } ctx.restore(); } function drawSelectionBorder(element) { let allmargin = margin if (border.show && borderImage && borderImage.complete) { allmargin = allmargin + border.width } const cornerRadius = canvas.height * 0.005; ctx.strokeStyle = 'red'; ctx.lineWidth = canvas.height * 0.002; if ('text' in element) { ctx.strokeRect((imgElm.width * element.x + allmargin), (imgElm.height * element.y + allmargin) - (imgElm.height * element.height), (imgElm.height * element.width), (imgElm.height * element.height)); } else if ('url' in element) { ctx.strokeRect((imgElm.width * element.x + allmargin), (imgElm.height * element.y + allmargin), (imgElm.height * element.width), (imgElm.height * element.height)); } else if (element === plottingScale) { ctx.strokeRect((imgElm.width * element.x + allmargin) - (plottingScale.width * 0.2), (imgElm.height * element.y + allmargin) - element.height - (plottingScale.height * 0.5), element.width + (plottingScale.width * 0.6), element.height + (plottingScale.height)); return } const corners = getCorners(element, allmargin); ctx.fillStyle = 'red'; corners.forEach(corner => { ctx.beginPath(); ctx.arc(corner.x, corner.y, cornerRadius, 0, 2 * Math.PI); ctx.fill(); }); } canvas.addEventListener('mousedown', function (e) { const x = getCanvasMouseX(e); const y = getCanvasMouseY(e); let allmargin = margin if (border.show && borderImage && borderImage.complete) { allmargin = allmargin + border.width } if (title.show) { // 检查是否点击了标题编辑触发区域 if (y >= ((title.height * imgElm.height) + allmargin) - triggerRange && y <= ((title.height * imgElm.height) + allmargin) + triggerRange) { isDragging = true; // 先将所有元素的选中状态置为 false for (let i = 0; i < data.length; i++) { data[i].isSelected = false; } selectedElement = null; isDraggingElement = false; isResizingElement = false; resizeCorner = null; return } } // 检查是否点击了边框角上的小圆点 if (selectedElement && selectedElement !== plottingScale) { const cornerRadius = canvas.height * 0.005; const corners = getCorners(selectedElement, allmargin); corners.forEach((corner, index) => { if (x >= corner.x - cornerRadius && x <= corner.x + cornerRadius && y >= corner.y - cornerRadius && y <= corner.y + cornerRadius) { isResizingElement = true; isDraggingElement = false; resizeCorner = index; startX = x; startY = y; elementWidth = (selectedElement.width * imgElm.height); elementHeight = (selectedElement.height * imgElm.height); if ('text' in selectedElement) { elementWidth = (selectedElement.width * imgElm.height); currentFontSize = selectedElement.height; } } }); } if (isResizingElement) { return } // 先将所有元素的选中状态置为 false for (let i = 0; i < data.length; i++) { data[i].isSelected = false; } plottingScale.isSelected = false; selectedElement = null; isDraggingElement = false; isResizingElement = false; resizeCorner = null; for (let i = data.length - 1; i >= 0; i--) { if (data[i].show) { if ('text' in data[i]) { if (x >= (imgElm.width * data[i].x) + allmargin && x <= (imgElm.width * data[i].x) + allmargin + (imgElm.height * data[i].width) && y >= (imgElm.height * data[i].y) + allmargin - (imgElm.height * data[i].height) && y <= (imgElm.height * data[i].y) + allmargin) { selectedElement = data[i]; data[i].isSelected = true; isDraggingElement = true; startX = x; startY = y; startY2 = (imgElm.height * data[i].y) - (imgElm.height * data[i].height) startX2 = (imgElm.width * data[i].x) + (imgElm.height * data[i].width) elementOffsetX = (imgElm.width * data[i].x) + allmargin; elementOffsetY = (imgElm.height * data[i].y) + allmargin; updateCanvas(); // 点击时重新绘制画布以显示边框 break; } } if ('url' in data[i]) { if (data[i].svg && data[i].svg.complete && data[i].show) { if (x >= (imgElm.width * data[i].x) + allmargin && x <= (imgElm.width * data[i].x) + allmargin + (imgElm.height * data[i].width) && y >= (imgElm.height * data[i].y) + allmargin && y <= (imgElm.height * data[i].y) + allmargin + (imgElm.height * data[i].height)) { selectedElement = data[i]; data[i].isSelected = true; isDraggingElement = true; startX = x; startY = y; startY2 = (imgElm.height * data[i].y) + (imgElm.height * data[i].height) startX2 = (imgElm.width * data[i].x) + (imgElm.height * data[i].width); elementOffsetX = (imgElm.width * data[i].x) + allmargin; elementOffsetY = (imgElm.height * data[i].y) + allmargin; updateCanvas(); // 点击时重新绘制画布以显示边框 break; } } } } } if (plottingScale.show) { if (x >= (imgElm.width * plottingScale.x + allmargin) - (plottingScale.width * 0.2) && x <= (imgElm.width * plottingScale.x + allmargin) - (plottingScale.width * 0.2) + plottingScale.width + (plottingScale.width * 0.6) && y >= (imgElm.height * plottingScale.y + allmargin) - plottingScale.height - (plottingScale.height * 0.5) && y <= (imgElm.height * plottingScale.y + allmargin) - (plottingScale.height * 0.5) + (plottingScale.height)) { selectedElement = plottingScale; plottingScale.isSelected = true; isDraggingElement = true; startX = x; startY = y; startY2 = (imgElm.height * plottingScale.y + allmargin) + plottingScale.height; startX2 = (imgElm.width * plottingScale.x + allmargin) + plottingScale.width; elementOffsetX = (imgElm.width * plottingScale.x + allmargin); elementOffsetY = imgElm.height * plottingScale.y + allmargin; updateCanvas(); // 点击时重新绘制画布以显示边框 } } // 如果点击在内容以外,重新绘制画布以移除边框 if (!selectedElement) { updateCanvas(); } }); canvas.addEventListener('mousemove', function (e) { let allmargin = margin if (border.show && borderImage && borderImage.complete) { allmargin = allmargin + border.width } const x = getCanvasMouseX(e); const y = getCanvasMouseY(e); if (x < 0 || y < 0 || x > canvas.width || y > canvas.height) { return } if (title.show) { let allmargin = margin if (border.show && borderImage && borderImage.complete) { allmargin = allmargin + border.width } if (y >= ((title.height * imgElm.height) + allmargin) - triggerRange && y <= ((title.height * imgElm.height) + allmargin) + triggerRange) { canvas.style.cursor = 'n-resize'; } else { canvas.style.cursor = 'default'; } if (isDragging) { title.height = Math.min(Math.max(y - allmargin, 30) / imgElm.height, 1); updateCanvas(); } } if (isDraggingElement) { const dx = x - startX; const dy = y - startY; selectedElement.x = ((elementOffsetX + dx) - allmargin) / imgElm.width; selectedElement.y = ((elementOffsetY + dy) - allmargin) / imgElm.height; updateCanvas(); } if (isResizingElement) { const dx = x - startX; const dy = y - startY; let scaleFactor; switch (resizeCorner) { case 0: // 左上角 if ('text' in selectedElement) { scaleFactor = (elementWidth - dx) / elementWidth; selectedElement.height = Math.max((10 / imgElm.height), currentFontSize * scaleFactor) selectedElement.x = (startX2 - (selectedElement.width * imgElm.height)) / imgElm.width; } else if ('url' in selectedElement) { selectedElement.x = (startX2 - (selectedElement.width * imgElm.height)) / imgElm.width; selectedElement.y = (startY2 - (selectedElement.height * imgElm.height)) / imgElm.height; selectedElement.width = Math.max(10, elementWidth - dx) / imgElm.height; selectedElement.height = Math.max(10, elementHeight - dy) / imgElm.height; } break; case 1: // 右上角 if ('text' in selectedElement) { scaleFactor = (elementWidth + dx) / elementWidth; selectedElement.height = Math.max((10 / imgElm.height), currentFontSize * scaleFactor); } else if ('url' in selectedElement) { selectedElement.width = Math.max(10, elementWidth + dx) / imgElm.height; selectedElement.height = Math.max(10, elementHeight - dy) / imgElm.height; selectedElement.y = (startY2 - (selectedElement.height * imgElm.height)) / imgElm.height; } break; case 2: // 左下角 if ('text' in selectedElement) { scaleFactor = (elementWidth - dx) / elementWidth; selectedElement.height = Math.max((10 / imgElm.height), currentFontSize * scaleFactor); selectedElement.x = (startX2 - (selectedElement.width * imgElm.height)) / imgElm.width; selectedElement.y = (startY2 + (selectedElement.height * imgElm.height)) / imgElm.height; } else if ('url' in selectedElement) { selectedElement.x = (startX2 - (selectedElement.width * imgElm.height)) / imgElm.width; selectedElement.width = Math.max(10, elementWidth - dx) / imgElm.height; selectedElement.height = Math.max(10, elementHeight + dy) / imgElm.height; } break; case 3: // 右下角 if ('text' in selectedElement) { scaleFactor = (elementWidth + dx) / elementWidth; selectedElement.height = Math.max((10 / imgElm.height), currentFontSize * scaleFactor); selectedElement.y = (startY2 + (selectedElement.height * imgElm.height)) / imgElm.height; } else if ('url' in selectedElement) { selectedElement.width = Math.max(10, elementWidth + dx) / imgElm.height; selectedElement.height = Math.max(10, elementHeight + dy) / imgElm.height; } break; } updateCanvas(); } }); document.addEventListener('mouseup', function () { isDragging = false; let allmargin = margin if (border.show && borderImage && borderImage.complete) { allmargin = allmargin + border.width } for (let i = 0; i < data.length; i++) { if (data[i].show && data[i].isSelected) { startY2 = (imgElm.height * data[i].y) - (imgElm.height * data[i].height) startX2 = (imgElm.width * data[i].x) + (imgElm.height * data[i].width) if ('url' in data[i]) { startY2 = (imgElm.height * data[i].y) + (imgElm.height * data[i].height) startX2 = (imgElm.width * data[i].x) + (imgElm.height * data[i].width); } elementOffsetX = data[i].x; elementOffsetY = data[i].y; } } if (plottingScale.show && plottingScale.isSelected) { startY2 = plottingScale.y + plottingScale.height startX2 = plottingScale.x + plottingScale.width elementOffsetX = plottingScale.x; elementOffsetY = plottingScale.y; } isDraggingElement = false; isResizingElement = false; resizeCorner = null; }); function getPlottingScale() { if (!rectangle) { return } let westLng = Cesium.Math.toDegrees(rectangle.west) let eastLng = Cesium.Math.toDegrees(rectangle.east) let northLat = Cesium.Math.toDegrees(rectangle.north) let southLat = Cesium.Math.toDegrees(rectangle.south) let from = turf.point([westLng, northLat]); let to = turf.point([eastLng, northLat]); let distance = turf.distance(from, to, { units: 'kilometers' }); unitDistance = distance * 1000 / imgElm.width; } function getDateTimeString() { // 创建一个表示当前时间的 Date 对象 const now = new Date(); // 获取年份 const year = now.getFullYear(); // 获取月份(从 0 开始,所以要加 1),并将其转换为两位字符串,不足两位在前面补零 const month = String(now.getMonth() + 1).padStart(2, '0'); // 获取日期,并将其转换为两位字符串,不足两位在前面补零 const day = String(now.getDate()).padStart(2, '0'); // 获取小时,并将其转换为两位字符串,不足两位在前面补零 const hours = String(now.getHours()).padStart(2, '0'); // 获取分钟,并将其转换为两位字符串,不足两位在前面补零 const minutes = String(now.getMinutes()).padStart(2, '0'); // 获取秒,并将其转换为两位字符串,不足两位在前面补零 const seconds = String(now.getSeconds()).padStart(2, '0'); // 获取毫秒,并将其转换为三位字符串,不足三位在前面补零 const milliseconds = String(now.getMilliseconds()).padStart(3, '0'); // 将年、月、日、时、分、秒、毫秒拼接成所需的字符串 return `${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`; } function exportMap() { let unitDistance2 let canvas2 = document.createElement('canvas'); let ctx2 = canvas2.getContext('2d'); let imgElm2 = new Image(); imgElm2.src = originalImg imgElm2.onload = function () { if (isLoad) { return } let title2 = { ...title } let data2 = JSON.parse(JSON.stringify(data)) let plottingScale2 = { ...plottingScale } let border2 = { ...border } border2.width = border.width / imgElm.width * imgElm2.width let margin2 = margin / imgElm.width * imgElm2.width; let allmargin = margin2 if (border2.show && borderImage && borderImage.complete) { allmargin = allmargin + border2.width } canvas2.width = imgElm2.width + (allmargin * 2); canvas2.height = imgElm2.height + (allmargin * 2); ctx2.clearRect(0, 0, canvas2.width, canvas2.height); ctx2.rect(0, 0, canvas2.width, canvas2.height); ctx2.fillStyle = "#ffffff"; ctx2.fill(); ctx2.drawImage(imgElm2, allmargin, allmargin, imgElm2.width, imgElm2.height); // 标题内容 if (title2.show) { const text = title2.text; const fontSize = Math.max(5, (title2.height * imgElm2.height) * 0.5); ctx2.font = `${fontSize}px serif`; ctx2.fillStyle = title2.bgColor || '#5d5d5d'; ctx2.fillRect(allmargin, allmargin, canvas2.width - (allmargin * 2), (title2.height * imgElm2.height)); ctx2.fillStyle = title2.color || 'white'; ctx2.textAlign = 'center'; ctx2.textBaseline = 'middle'; ctx2.fillText(text, canvas2.width / 2, ((title2.height * imgElm2.height) / 2) + allmargin); } // 其他内容 for (let i = 0; i < data2.length; i++) { if (data2[i].show) { if ('text' in data2[i]) { ctx2.font = `${imgElm2.height * data2[i].height}px serif`; ctx2.fillStyle = data2[i].color || 'white'; ctx2.textAlign = 'left'; ctx2.textBaseline = 'bottom'; data2[i].width = ctx2.measureText(data2[i].text).width / imgElm2.height; ctx2.fillText(data2[i].text, (imgElm2.width * data2[i].x) + allmargin, (imgElm2.height * data2[i].y) + allmargin); } else if ('url' in data2[i]) { if (data[i].svg && data[i].svg.complete) { ctx2.drawImage(data[i].svg, (imgElm2.width * data2[i].x) + allmargin, (imgElm2.height * data2[i].y) + allmargin, imgElm2.height * data2[i].width, imgElm2.height * data2[i].height); } else { const svg = new Image(); svg.src = tools.getSourceRootPath() + data2[i].url; svg.onload = function () { data2[i].svg = svg ctx2.drawImage(svg, (imgElm2.width * data2[i].x) + allmargin, (imgElm2.height * data2[i].y) + allmargin, imgElm2.height * data2[i].width, imgElm2.height * data2[i].height) } } } } } // 比例尺 if (plottingScale2.show) { getPlottingScale() let plottingScale2X = imgElm2.width * plottingScale2.x + allmargin let plottingScale2Y = imgElm2.height * plottingScale2.y + allmargin let unit = 'm' // const fontSize = plottingScale2.width * 0.12; const fontSize = imgElm2.width * 0.08 * 0.12; let spacing = imgElm2.width * 0.08 / plottingScale2.cell; let spacingDistance = Math.round(unitDistance2 * spacing); let spacingDistanceString = spacingDistance + '' if (spacingDistance < 10) { } else { spacingDistance = Number(spacingDistanceString[0]) for (let i = 0; i < spacingDistanceString.length - 1; i++) { spacingDistance = spacingDistance * 10 } spacing = spacingDistance / unitDistance2 } plottingScale2.width = spacing * plottingScale2.cell; plottingScale2.height = plottingScale2.width * 0.2; if (spacingDistance >= 1000) { unit = '㎞' spacingDistance = Math.round(spacingDistance / 1000); } const scaleY = plottingScale2Y; ctx2.beginPath(); ctx2.moveTo(plottingScale2X, scaleY); ctx2.lineTo(plottingScale2X + plottingScale2.width, scaleY); ctx2.strokeStyle = plottingScale2.color; ctx2.lineWidth = plottingScale2.width * 0.01; ctx2.stroke(); let tickX = 0 for (let i = 0; i <= plottingScale2.cell; i++) { tickX = plottingScale2X + i * spacing; ctx2.beginPath(); ctx2.moveTo(tickX, scaleY - plottingScale2.width * 0.1); ctx2.lineTo(tickX, scaleY); ctx2.strokeStyle = plottingScale2.color; ctx2.lineWidth = plottingScale2.width * 0.01; ctx2.stroke(); ctx2.font = `${fontSize}px Arial`; ctx2.fillStyle = plottingScale2.color; ctx2.textAlign = 'center'; ctx2.textBaseline = 'bottom'; ctx2.fillText(i * spacingDistance, tickX, scaleY - plottingScale2.width * 0.1); } ctx2.font = `${fontSize}px Arial`; ctx2.fillStyle = plottingScale2.color; ctx2.textAlign = 'left'; ctx2.textBaseline = 'bottom'; ctx2.fillText(unit, tickX + (fontSize * 1.2), scaleY - plottingScale2.width * 0.1); } // 边框 if (border2.show && borderImage && borderImage.complete) { // 绘制四个角(裁剪成45度角) drawBorder2(ctx2, borderImage, margin2, margin2, border2.width, 'top', 1); drawBorder2(ctx2, borderImage, canvas2.width - border2.width - margin2, margin2, border2.width, 'right', 1); drawBorder2(ctx2, borderImage, canvas2.width - border2.width - margin2, canvas2.height - border2.width - margin2, border2.width, 'bottom', 1); drawBorder2(ctx2, borderImage, margin2, canvas2.height - border2.width - margin2, border2.width, 'left', 1); } function getPlottingScale() { if (!rectangle) { return } let westLng = Cesium.Math.toDegrees(rectangle.west) let eastLng = Cesium.Math.toDegrees(rectangle.east) let northLat = Cesium.Math.toDegrees(rectangle.north) let southLat = Cesium.Math.toDegrees(rectangle.south) let from = turf.point([westLng, northLat]); let to = turf.point([eastLng, northLat]); let distance = turf.distance(from, to, { units: 'kilometers' }); unitDistance2 = distance * 1000 / imgElm2.width; } // 绘制边框 function drawBorder2(ctx2, img, x, y, size, position, isStart = 1) { ctx2.save(); ctx2.translate(x + size / 2, y + size / 2); // 根据位置设置旋转角度 switch (position) { case 'right': ctx2.rotate(Math.PI / 2); break; case 'bottom': ctx2.rotate(Math.PI); break; case 'left': ctx2.rotate(3 * Math.PI / 2); break; } // 创建45度角的裁剪路径 ctx2.beginPath(); ctx2.moveTo((-size * isStart) / 2, -size / 2); if (position === 'top' || position === 'bottom') { ctx2.lineTo(canvas2.width - (margin2 * 2) - (size / 2), -size / 2); ctx2.lineTo(canvas2.width - (margin2 + size) * 2 + (size / 2), size / 2); } else { ctx2.lineTo(canvas2.height - (margin2 * 2) - (size / 2), -size / 2); ctx2.lineTo(canvas2.height - (margin2 + size) * 2 + (size / 2), size / 2); } ctx2.lineTo((size * isStart) / 2, size / 2); ctx2.closePath(); ctx2.clip(); let imgWidth = img.width / img.height * size // 绘制图片 ctx2.drawImage(img, -size / 2, -size / 2, imgWidth, size); let count; if (position === 'top' || position === 'bottom') { count = Math.ceil((canvas2.width - (margin2 * 2) - (border2.width * 2)) / border2.width); } else { count = Math.ceil((canvas2.height - (margin2 * 2) - (border2.width * 2)) / border2.width); } count++ for (let i = 1; i <= count; i++) { ctx2.drawImage(img, -size / 2 + imgWidth * i, -size / 2, imgWidth, size); } ctx2.restore(); } // let dataURL = canvas2.toDataURL('image/jpeg', 0.95) // let downloadElement = document.createElement('a'); // downloadElement.href = dataURL; // downloadElement.download = `高清出图-${getDateTimeString()}.jpg`; // document.body.appendChild(downloadElement); // downloadElement.click(); // document.body.removeChild(downloadElement); // console.log('dataURL', dataURL) // URL.revokeObjectURL(dataURL); // 在释放资源后执行回调 canvas2.toBlob(function (blob) { const url = URL.createObjectURL(blob); let downloadElement = document.createElement('a'); downloadElement.href = url; downloadElement.download = `高清出图-${getDateTimeString()}.png`; document.body.appendChild(downloadElement); downloadElement.click(); document.body.removeChild(downloadElement); }, 'image/png', 0.95); exporting = false; exportBtn.innerHTML = '打印'; // canvas2.toBlob(function (blob) { // let imgBlobData = URL.createObjectURL(blob); // let downloadElement = document.createElement('a'); // downloadElement.href = imgBlobData; // downloadElement.download = `高清出图-${getDateTimeString()}.png`; // document.body.appendChild(downloadElement); // downloadElement.click(); // document.body.removeChild(downloadElement); // URL.revokeObjectURL(imgBlobData); // // 在释放资源后执行回调 // exporting = false; // exportBtn.innerHTML = '打印'; // }); } } } export default MapPrint