2025-07-03 13:54:01 +08:00
|
|
|
|
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 = `
|
|
|
|
|
<div class="left">
|
|
|
|
|
<div class="div-item">
|
|
|
|
|
<div class="title">图件信息</div>
|
|
|
|
|
<div class="row" style="align-items: flex-start;">
|
|
|
|
|
<div class="col template-box">
|
|
|
|
|
<span class="label" style="flex: 0 0 56px;">模板</span>
|
|
|
|
|
<div class="template" style="width: 213px;"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row" style="align-items: flex-start;">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<span class="label" style="flex: 0 0 56px;">标题</span>
|
|
|
|
|
<input class="title-input" type="text">
|
|
|
|
|
<input class="title-checkbox" type="checkbox" style="margin-left: 15px;">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row" style="align-items: flex-start;">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<span class="label" style="flex: 0 0 56px;">制图日期</span>
|
|
|
|
|
<input class="print-date" type="text" placeholder="YYYY-MM-DD" readonly>
|
|
|
|
|
<input class="print-date-checkbox" type="checkbox" style="margin-left: 15px;">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row" style="align-items: flex-start;">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<span class="label" style="flex: 0 0 56px;">制图单位</span>
|
|
|
|
|
<input class="unit-input" type="text">
|
|
|
|
|
<input class="unit-checkbox" type="checkbox" style="margin-left: 15px;">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row" style="align-items: flex-start;">
|
|
|
|
|
<div class="col map-border-box">
|
|
|
|
|
<span class="label" style="flex: 0 0 56px;">图框</span>
|
|
|
|
|
<div class="map-border" style="width: 173px;"></div>
|
|
|
|
|
<div class="border-color" style="margin-top: 3px;margin-left: 12px;"></div>
|
|
|
|
|
<input class="map-border-checkbox" type="checkbox" style="margin-left: 15px;">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="div-item">
|
|
|
|
|
<div class="title">地图要素</div>
|
|
|
|
|
<div class="row" style="align-items: flex-start;">
|
|
|
|
|
<div class="col" style="align-items: flex-start;">
|
|
|
|
|
<span class="label" style="flex: 0 0 56px;margin-top: 9px;">指北针</span>
|
|
|
|
|
<input class="compass-checkbox" type="checkbox" style="margin-top: 11px;">
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col" style="margin-left: 10px;flex-wrap: wrap;">
|
|
|
|
|
${(() => {
|
|
|
|
|
let str = '';
|
|
|
|
|
for (let i = 0; i < compassList.length; i++) {
|
|
|
|
|
const compass = tools.getSourceRootPath() + compassList[i];
|
|
|
|
|
str += `<div style="display: flex;align-items: center;">
|
|
|
|
|
<input class="compass-radio" type="radio" name="option">
|
|
|
|
|
<img src="${compass}" alt="" style="width: 38px; height: 38px; margin: 0 5px;">
|
|
|
|
|
</div>`
|
|
|
|
|
}
|
|
|
|
|
return str
|
|
|
|
|
})()}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row" style="align-items: flex-start;">
|
|
|
|
|
<div class="col" style="align-items: flex-start;">
|
|
|
|
|
<span class="label" style="flex: 0 0 56px;margin-top: 9px;">比例尺</span>
|
|
|
|
|
<input class="plotting-scale-checkbox" type="checkbox" style="margin-top: 11px;">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="right">
|
|
|
|
|
<div class="map-img-box">
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
`;
|
|
|
|
|
_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()
|
|
|
|
|
}
|
|
|
|
|
})
|
2025-07-16 15:02:18 +08:00
|
|
|
|
let borderColorPicker = new YJColorPicker({
|
2025-07-03 13:54:01 +08:00
|
|
|
|
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 = '<span style="position: absolute;width:100%;height:100%;top: 0;left: 0;border-radius: 3px;background-color: #6f89848f;"><svg class="icon-load"><use xlink:href="#yj-icon-load"></use></svg></span>打印'
|
|
|
|
|
exportMap()
|
|
|
|
|
// exporting = true
|
|
|
|
|
// exportBtn.innerHTML = '<span style="position: absolute;width:100%;height:100%;top: 0;left: 0;border-radius: 3px;background-color: #6f89848f;"><svg class="icon-load"><use xlink:href="#yj-icon-load"></use></svg></span>打印'
|
|
|
|
|
// 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: `<span style="background-image: url(${tools.getSourceRootPath()}/custom/img/map-border1.svg);background-size: auto 100%;background-repeat: repeat-x;"></span>`,
|
|
|
|
|
value: '/custom/img/map-border1.svg',
|
|
|
|
|
key: 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: `<span style="background-image: url(${tools.getSourceRootPath()}/custom/img/map-border2.svg);background-size: auto 100%;background-repeat: repeat-x;"></span>`,
|
|
|
|
|
value: '/custom/img/map-border2.svg',
|
|
|
|
|
key: 1,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: `<span style="background-image: url(${tools.getSourceRootPath()}/custom/img/map-border3.svg);background-size: auto 100%;background-repeat: repeat-x;"></span>`,
|
|
|
|
|
value: '/custom/img/map-border3.svg',
|
|
|
|
|
key: 2,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: `<span style="background-image: url(${tools.getSourceRootPath()}/custom/img/map-border4.svg);background-size: auto 100%;background-repeat: repeat-x;"></span>`,
|
|
|
|
|
value: '/custom/img/map-border4.svg',
|
|
|
|
|
key: 3,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: `<span style="background-image: url(${tools.getSourceRootPath()}/custom/img/map-border5.svg);background-size: auto 100%;background-repeat: repeat-x;"></span>`,
|
|
|
|
|
value: '/custom/img/map-border5.svg',
|
|
|
|
|
key: 4,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: `<span style="background-image: url(${tools.getSourceRootPath()}/custom/img/map-border6.svg);background-size: auto 100%;background-repeat: repeat-x;"></span>`,
|
|
|
|
|
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'
|
2025-07-16 15:02:18 +08:00
|
|
|
|
new YJColorPicker({
|
2025-07-03 13:54:01 +08:00
|
|
|
|
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;
|
2025-08-08 10:03:42 +08:00
|
|
|
|
downloadElement.download = `高清出图-${getDateTimeString()}.png`;
|
2025-07-03 13:54:01 +08:00
|
|
|
|
document.body.appendChild(downloadElement);
|
|
|
|
|
downloadElement.click();
|
|
|
|
|
document.body.removeChild(downloadElement);
|
2025-08-08 10:03:42 +08:00
|
|
|
|
}, 'image/png', 0.95);
|
2025-07-03 13:54:01 +08:00
|
|
|
|
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
|