import Tools from '../../Tools'
import Dialog from '../../Obj/Element/Dialog';
import { legp } from '../../Obj/Element/datalist';
import MapPrint from '../MapPrint';
import { off as offSplitScreen } from "../SplitScreen";
import { off as offMultiViewportMode } from "../MultiViewportMode";
// 生成快照
const convertToImage = (container, options = {}) => {
// 设置放大倍数
const scale = window.devicePixelRatio;
// 传入节点原始宽高
const width = container.offsetWidth;
const height = container.offsetHeight;
// html2canvas配置项
const ops = {
scale,//比例,越大分辨率越高,图片越小
width,
height,
async: false,
x: 0,
y: 0,
backgroundColor: 'rgb(20,47,65)',
imageTimeout: 0,
useCORS: true,//允许跨域
allowTaint: false, //允许跨域数据污染'被污染'的canvas
tainttest: true,
foreignObjectRendering: true, //在浏览器支持的情况下使用ForeignObject模式渲染图片
...options
};
return html2canvas(container, ops).then(canvas => {
// 返回图片的二进制数据
return canvas.toDataURL("image/png");
});
}
async function ScreenShot(sdk, cd = () => { }) {
// const imgBlobData = await convertToImage(sdk.viewer.canvas);
const imgBlobData = sdk.viewer.canvas.toDataURL()
cd && cd(imgBlobData)
// try {
// const imgBlobData = await convertToImage(sdk.viewer.canvas);
// let arr = imgBlobData.split(','), mime = arr[0].match(/:(.*?);/)[1],
// bstr = atob(arr[1]), i = bstr.length, u8arr = new Uint8Array(i);
// while (i--) {
// u8arr[i] = bstr.charCodeAt(i);
// }
// let blob = new Blob([u8arr], { type: mime });
// const opts = {
// suggestedName: '截图.png',
// types: [
// {
// description: '文件类型',
// accept: {
// 'image/png': ['.png'],
// 'image/jpg': ['.jpg']
// }
// }
// ],
// excludeAcceptAllOption: true
// };
// const handle = await window.showSaveFilePicker(opts); // 打开保存文件对话框
// const writable = await handle.createWritable(); // 创建可写入的文件对象
// // 写入视频内容
// writable.write(blob);
// await writable.close();
// YJ.Global.ScreenRecord.screenRecord = null
// } catch (error) {
// console.info('文件保存失败:', error);
// }
}
let _DialogObject
async function ScreenShotHD(sdk, options = {}, cd = () => { }) {
if (!sdk) {
return
}
offSplitScreen(sdk)
offMultiViewportMode(sdk)
if (_DialogObject) {
_DialogObject.close()
_DialogObject = null
}
let enableTranslate = sdk.viewer.scene.screenSpaceCameraController.enableTranslate
let enableTilt = sdk.viewer.scene.screenSpaceCameraController.enableTilt
let enableLook = sdk.viewer.scene.screenSpaceCameraController.enableLook
let scale = 1
let level
let progressInputElm
let progressBarElm
let rangeNodeActive
let rangeNodeActiveText
let startScreenShotObject
let tools = new Tools();
_DialogObject = await new Dialog(sdk, {}, {
title: '高清出图', left: '180px', top: '100px',
confirmCallBack: (options) => {
if (startScreenShotObject) {
startScreenShotObject.desist()
startScreenShotObject = null
}
progressInputElm && (progressInputElm.style.width = '0%')
rangeNodeActive && (rangeNodeActive.style.left = '0%')
progressBarElm && (progressBarElm.style.width = '0%')
rangeNodeActiveText && (rangeNodeActiveText.innerHTML = '0%')
startScreenShotObject = new startScreenShot()
},
closeCallBack: () => {
sdk.viewer.scene.screenSpaceCameraController.enableTranslate = enableTranslate;
sdk.viewer.scene.screenSpaceCameraController.enableTilt = enableTilt;
sdk.viewer.scene.screenSpaceCameraController.enableLook = enableLook;
sdk.viewer._element.getElementsByClassName('compass')[0].style.pointerEvents = 'auto'
if (startScreenShotObject) {
startScreenShotObject.desist()
startScreenShotObject = null
}
_DialogObject = undefined
}
})
_DialogObject._element.body.className = _DialogObject._element.body.className + ' screenShotHD'
let contentElm = document.createElement('div');
contentElm.innerHTML = `
当前窗口长宽:${sdk.viewer.canvas.width}*${sdk.viewer.canvas.height}像素
输出图片长宽:${sdk.viewer.canvas.width * scale}*${sdk.viewer.canvas.height * scale}像素
`
_DialogObject.contentAppChild(contentElm)
sdk.viewer.scene.screenSpaceCameraController.enableTranslate = false;
sdk.viewer.scene.screenSpaceCameraController.enableTilt = false;
sdk.viewer.scene.screenSpaceCameraController.enableLook = false;
sdk.viewer._element.getElementsByClassName('compass')[0].style.pointerEvents = 'none'
let centerResult = sdk.viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(
sdk.viewer.canvas.clientWidth / 2,
sdk.viewer.canvas.clientHeight / 2,
),
)
if (!centerResult) {
centerResult = sdk.viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(
sdk.viewer.canvas.clientWidth / 2,
sdk.viewer.canvas.clientHeight / (2 - ((90 + sdk.viewer.camera.pitch / (Cesium.Math.PI / 180)) / 110)),
),
)
if (!centerResult) {
centerResult = sdk.viewer.camera.position
}
}
let height = tools.cartesian3Towgs84(sdk.viewer.camera.position, sdk.viewer).alt
let centerResult84 = tools.cartesian3Towgs84(centerResult, sdk.viewer)
sdk.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(centerResult84.lng, centerResult84.lat, height),
orientation: { heading: 0, pitch: Cesium.Math.toRadians(-90), roll: 0 },
duration: 1,
})
let scaleData = []
for (let i = 1; i <= 10; i++) {
scaleData.push({
name: i,
value: i
})
}
progressInputElm = document.getElementsByClassName('progress-input')[0]
progressBarElm = document.getElementsByClassName('range-process')[0]
rangeNodeActive = contentElm.getElementsByClassName('range-node-active')[0]
rangeNodeActiveText = contentElm.getElementsByClassName('range-node-active-text')[0]
let scaleDataLegpObject = legp(_DialogObject._element.content.getElementsByClassName('scale-box')[0], ".scale")
if (scaleDataLegpObject) {
scaleDataLegpObject.legp_search(scaleData)
let scaleDataLegpElm = _DialogObject._element.content.getElementsByClassName('scale')[0].getElementsByTagName('input')[0]
scale = scaleData[0].value
scaleDataLegpObject.legp_searchActive(scaleData[0].value)
scaleDataLegpElm.value = scaleData[0].value
scaleDataLegpElm.addEventListener('input', () => {
for (let i = 0; i < scaleData.length; i++) {
if (scaleData[i].value == scaleDataLegpElm.value) {
scale = scaleData[i].value
_DialogObject._element.content.getElementsByClassName('output-width')[0].innerHTML = sdk.viewer.canvas.width * scale
_DialogObject._element.content.getElementsByClassName('output-height')[0].innerHTML = sdk.viewer.canvas.height * scale
break
}
}
})
}
class startScreenShot {
constructor() {
this.state = false
this.start()
}
start() {
if (sdk.viewer.scene.imageryLayers._layers.length <= 1) {
this.error = '未加载底图!'
window.ELEMENT && window.ELEMENT.Message({
message: this.error,
type: 'warning',
duration: 1500
});
console.warn(this.error)
return
}
let haveBaseMap = false
for (let i = 0; i < sdk.viewer.scene.imageryLayers._layers.length; i++) {
let layer = sdk.viewer.scene.imageryLayers._layers[i];
if (layer && layer.show && (!layer.notes || layer.notes !== 'default-base-map')) {
haveBaseMap = true
}
}
if (!haveBaseMap) {
this.error = '未加载底图!'
window.ELEMENT && window.ELEMENT.Message({
message: this.error,
type: 'warning',
duration: 1500
});
console.warn(this.error)
return
}
let scaleZoom = 0;
this.state = true;
let _this = this
computeLayers(1);
function computeLayers(s) {
let num = s * 2;
if (num <= scale) {
scaleZoom++;
computeLayers(num);
}
}
scaleZoom = scaleZoom + 1;
let centerResult = sdk.viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(
sdk.viewer.canvas.width / 2,
sdk.viewer.canvas.height / (2 - ((90 + sdk.viewer.camera.pitch / (Cesium.Math.PI / 180)) / 110))
)
);
if (!centerResult) {
centerResult = sdk.viewer.camera.position;
}
function altitudeToZoom(altitude) {
let A = 40487.57;
let B = 0.00007096758;
let C = 91610.74;
let D = -40467.74;
return Math.round(D + (A - D) / (1 + Math.pow(altitude / C, B)));
}
let height = tools.cartesian3Towgs84(sdk.viewer.camera.position, sdk.viewer).alt;
let zoom = altitudeToZoom(height) + 1;
let rectangle = sdk.viewer.camera.computeViewRectangle();
// if (height > 9000000) {
// height = 9000000
// }
// let curRectangle = new Cesium.Rectangle(Cesium.Math.toRadians(centerResult84.lng - (height / stepX)), Cesium.Math.toRadians(centerResult84.lat - (height / stepY)), Cesium.Math.toRadians(centerResult84.lng + (height / stepX)), Cesium.Math.toRadians(centerResult84.lat + (height / stepY)))
// for (let i = 1; i < sdk.viewer.scene.imageryLayers._layers.length; i++) {
// let layer = sdk.viewer.scene.imageryLayers._layers[i]
// createCanvas(layer)
// }
let total;
let totalCount = 0;
let progress = {};
let index = 0;
let layerLength = 0
let countIndex = 0
for (let i = 0; i < sdk.viewer.scene.imageryLayers._layers.length; i++) {
let layer = sdk.viewer.scene.imageryLayers._layers[i];
if (layer && layer.show && layer.imageryProvider && layer.imageryProvider.url && Cesium.Rectangle.intersection(rectangle, layer.imageryProvider.rectangle) && (!layer.notes || layer.notes !== 'default-base-map')) {
layerLength++
}
}
let itemTotalProgress = 100 / layerLength
let flag = false
createCanvas(index);
function createCanvas(i, totalCanvas) {
let layer = sdk.viewer.scene.imageryLayers._layers[i];
if (!layer) {
if (!flag) {
_this.error = '当前范围内未找到底图数据!'
window.ELEMENT && window.ELEMENT.Message({
message: _this.error,
type: 'warning',
duration: 1500
});
console.warn(_this.error)
}
return
}
if (!layer.show || !layer.imageryProvider || !layer.imageryProvider.url || !Cesium.Rectangle.intersection(rectangle, layer.imageryProvider.rectangle) || (layer.notes && layer.notes === 'default-base-map')) {
let m = i += 1;
createCanvas(m, totalCanvas);
return;
}
flag = true
countIndex++
progress[i] = {
value: 0
}
let itemTotalCount = 0;
let targetLevel
let imageryProvider = layer.imageryProvider;
if (level || level === 0) {
targetLevel = level
}
else {
targetLevel = (zoom + scaleZoom - 1)
if (targetLevel > imageryProvider.maximumLevel) {
targetLevel = imageryProvider.maximumLevel
}
if (targetLevel < imageryProvider.minimumLevel) {
targetLevel = imageryProvider.minimumLevel
}
}
function readyPromise() {
let MinTile = imageryProvider.tilingScheme.positionToTileXY(
Cesium.Rectangle.northwest(rectangle),
targetLevel
);
let MaxTile = imageryProvider.tilingScheme.positionToTileXY(
Cesium.Rectangle.southeast(rectangle),
targetLevel
);
if (!MinTile || !MaxTile) {
let error = '超出地球范围!'
window.ELEMENT && window.ELEMENT.Message({
message: error,
type: 'warning',
duration: 1500
});
console.warn(error)
return
}
let OfXTilesAtLevel = imageryProvider.tilingScheme.getNumberOfXTilesAtLevel(targetLevel)
let OfYTilesAtLevel = imageryProvider.tilingScheme.getNumberOfYTilesAtLevel(targetLevel)
let MinTileX = MinTile.x;
let MinTileY = MinTile.y;
let MaxTileX = MaxTile.x;
let MaxTileY = MaxTile.y;
// if (MinTileX > MaxTileX) {
// MinTileX = MinTileX - OfXTilesAtLevel
// }
let imgWidth = 256;
let imgHeight = 256;
let itemTotal = (MaxTileX - MinTileX + 1) * (MaxTileY - MinTileY + 1);
// var canvas = new fabric.Canvas();
let canvas = document.createElement('canvas');
canvas.width = (MaxTileX - MinTileX + 1) * imgWidth;
canvas.height = (MaxTileY - MinTileY + 1) * imgHeight;
let ctx = canvas.getContext('2d');
let maxRectangle = imageryProvider.tilingScheme.tileXYToRectangle(MaxTileX, MaxTileY, targetLevel);
let minRectangle = imageryProvider.tilingScheme.tileXYToRectangle(MinTileX, MinTileY, targetLevel);
let canvasNativeRectangle = new Cesium.Rectangle(minRectangle.west, maxRectangle.south, maxRectangle.east, minRectangle.north);
// sdk.viewer.entities.add({
// rectangle: {
// coordinates: canvasNativeRectangle,
// material: Cesium.Color.YELLOW.withAlpha(0.2),
// },
// });
// sdk.viewer.entities.add({
// rectangle: {
// coordinates: rectangle,
// material: Cesium.Color.BLACK.withAlpha(0.2),
// },
// });
let nativeRectangle = rectangle;
let x1 = nativeRectangle.west - canvasNativeRectangle.west;
let x2 = canvasNativeRectangle.east - nativeRectangle.east;
let y1 = canvasNativeRectangle.north - nativeRectangle.north;
let y2 = nativeRectangle.south - canvasNativeRectangle.south;
let ratioX1 = x1 / (canvasNativeRectangle.east - canvasNativeRectangle.west);
if (ratioX1 === Infinity) {
ratioX1 = 0;
}
let ratioX2 = x2 / (canvasNativeRectangle.east - canvasNativeRectangle.west);
if (ratioX2 === Infinity) {
ratioX2 = 0;
}
let ratioY1 = y1 / (canvasNativeRectangle.north - canvasNativeRectangle.south);
if (ratioY1 === Infinity) {
ratioY1 = 0;
}
let ratioY2 = y2 / (canvasNativeRectangle.north - canvasNativeRectangle.south);
if (ratioY2 === Infinity) {
ratioY2 = 0;
}
let differenceX1 = canvas.width * ratioX1;
let differenceY1 = canvas.height * ratioY1;
let differenceX2 = canvas.width * ratioX2;
let differenceY2 = canvas.height * ratioY2;
canvas.width = canvas.width - differenceX1 - differenceX2;
canvas.height = canvas.height - differenceY1 - differenceY2;
if (canvas.width == 0) {
canvas.width = 1
}
if (canvas.height == 0) {
canvas.height = 1
}
let y = MaxTileY;
let x = MaxTileX;
let tileArray = []
for (let y = MaxTileY; y >= MinTileY; y--) {
for (let x = MaxTileX; x >= MinTileX; x--) {
tileArray.push({ x, y })
}
}
let speed = 30
let obj = {
count: 0
};
let count = 0;
let times = -1
let obj2 = {
count: 0
}
let count2 = 0
Object.defineProperty(obj2, 'count', {
get: function () {
return count2;
},
set: function (newValue) {
count2 = newValue;
if (count2 >= speed) {
traversal10()
}
}
});
Object.defineProperty(obj, 'count', {
get: function () {
return count;
},
set: function (newValue) {
count = newValue;
progress[i].value = itemTotalCount / itemTotal * itemTotalProgress;
let totalProgress = 0
for (const key in progress) {
totalProgress = totalProgress + progress[key].value
}
progressBarElm.style.width = totalProgress * 0.99 + '%';
rangeNodeActive.style.left = totalProgress * 0.99 + '%';
rangeNodeActiveText.innerHTML = Math.floor(totalProgress * 0.99 * 100) / 100 + '%';
if (count === (MaxTileX - MinTileX + 1) * (MaxTileY - MinTileY + 1)) {
let ctx = canvas.getContext('2d');
let cloneCanvas = canvas.cloneNode(true);
let cloneCtx = cloneCanvas.getContext('2d');
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
cloneCtx.putImageData(imageData, 0, 0);
canvas.width = sdk.viewer.canvas.width * scale;
canvas.height = sdk.viewer.canvas.height * scale;
ctx.drawImage(cloneCanvas, 0, 0, canvas.width, canvas.height);
if (totalCanvas) {
let ctx = totalCanvas.getContext('2d');
ctx.drawImage(canvas, 0, 0);
if (countIndex != layerLength) {
let m = i += 1;
createCanvas(m, totalCanvas);
return;
}
else {
let imgBlobData = totalCanvas.toDataURL('image/jpeg', 0.95);
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = totalCanvas.width / scale
tempCanvas.height = totalCanvas.height / scale
tempCtx.drawImage(totalCanvas, 0, 0, tempCanvas.width, tempCanvas.height);
MapPrint(sdk, tempCanvas.toDataURL('image/jpeg', 0.95), rectangle, imgBlobData)
progressBarElm.style.width = '100%';
rangeNodeActive.style.left = '100%';
rangeNodeActiveText.innerHTML = '100%';
_this.state = false
}
}
else {
if (countIndex != layerLength) {
let m = i += 1;
createCanvas(m, canvas);
return;
}
else {
let imgBlobData = canvas.toDataURL('image/jpeg', 0.95);
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = canvas.width / scale;
tempCanvas.height = canvas.height / scale;
tempCtx.drawImage(canvas, 0, 0, tempCanvas.width, tempCanvas.height);
// canvas.width = canvas.width / scale
// canvas.height = canvas.height / scale
MapPrint(sdk, tempCanvas.toDataURL('image/jpeg', 0.95), rectangle, imgBlobData)
progressBarElm.style.width = '100%';
rangeNodeActive.style.left = '100%';
rangeNodeActiveText.innerHTML = '100%';
_this.state = false
}
}
}
}
});
if (imageryProvider._readyError) {
obj.count = (MaxTileX - MinTileX + 1) * (MaxTileY - MinTileY + 1)
}
else {
traversal10()
}
function traversal10() {
obj2.count = 0
count2 = 0
times++
for (let i = times * speed; i < (times + 1) * speed; i++) {
if (i >= tileArray.length) {
return
}
traversal(i)
}
}
function traversal(i) {
if (!_this.state) {
return
}
try {
let x = tileArray[i].x
if (x < 0) {
x = x + OfXTilesAtLevel
}
const img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = async function () {
ctx.drawImage(img, ((tileArray[i].x - MinTileX) * imgWidth) - parseFloat(differenceX1.toFixed(0)), ((tileArray[i].y - MinTileY) * imgHeight) - parseFloat(differenceY1.toFixed(0)), imgWidth, imgHeight);
itemTotalCount++;
obj.count++;
obj2.count++;
};
img.onerror = function () {
itemTotalCount++;
obj.count++;
obj2.count++;
};
let url;
if (imageryProvider.url.indexOf('{x}') !== -1 && imageryProvider.url.indexOf('{y}') !== -1 && imageryProvider.url.indexOf('{z}') !== -1) {
url = imageryProvider.url.replace(/\{x\}/g, x).replace(/\{y\}/g, tileArray[i].y).replace(/\{z\}/g, targetLevel);
}
else if (imageryProvider.url.indexOf('{TileMatrix}') !== -1 && imageryProvider.url.indexOf('{TileRow}') !== -1 && imageryProvider.url.indexOf('{TileCol}') !== -1) {
url = imageryProvider.url.replace(/\{TileCol\}/g, x).replace(/\{TileRow\}/g, tileArray[i].y).replace(/\{TileMatrix\}/g, targetLevel);
}
else if (imageryProvider._layer && imageryProvider._style && imageryProvider._tileMatrixSetID && imageryProvider._format) {
url = imageryProvider.url + `&tilematrix=${targetLevel}&layer=${imageryProvider._layer}&style=${imageryProvider._style}&tilerow=${y}&tilecol=${x}&tilematrixset=${imageryProvider._tileMatrixSetID}&format=${imageryProvider._format}`;
}
else {
url = imageryProvider.url + `tile/${targetLevel}/${tileArray[i].y}/${x}`;
}
img.src = url;
} catch (error) {
itemTotalCount++;
obj.count++;
obj2.count++;
}
}
function traversal2() {
if (!_this.state) {
return
}
try {
const img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = async function () {
ctx.drawImage(img, ((x - MinTileX) * imgWidth) - parseFloat(differenceX1.toFixed(0)), ((y - MinTileY) * imgHeight) - parseFloat(differenceY1.toFixed(0)), imgWidth, imgHeight);
itemTotalCount++;
obj.count++;
if (x > MinTileX) {
x--
}
else {
if (y > MinTileY) {
y--
x = MaxTileX
}
else {
return
}
}
traversal()
};
let url;
if (imageryProvider.url.indexOf('{x}') !== -1 && imageryProvider.url.indexOf('{y}') !== -1 && imageryProvider.url.indexOf('{z}') !== -1) {
url = imageryProvider.url.replace(/\{x\}/g, x).replace(/\{y\}/g, y).replace(/\{z\}/g, targetLevel);
}
else if (imageryProvider.url.indexOf('{TileMatrix}') !== -1 && imageryProvider.url.indexOf('{TileRow}') !== -1 && imageryProvider.url.indexOf('{TileCol}') !== -1) {
url = imageryProvider.url.replace(/\{TileCol\}/g, x).replace(/\{TileRow\}/g, y).replace(/\{TileMatrix\}/g, targetLevel);
}
else if (imageryProvider._layer && imageryProvider._style && imageryProvider._tileMatrixSetID && imageryProvider._format) {
url = imageryProvider.url + `&tilematrix=${targetLevel}&layer=${imageryProvider._layer}&style=${imageryProvider._style}&tilerow=${y}&tilecol=${x}&tilematrixset=${imageryProvider._tileMatrixSetID}&format=${imageryProvider._format}`;
}
else {
url = imageryProvider.url + `tile/${targetLevel}/${y}/${x}`;
}
img.src = url;
} catch (error) {
itemTotalCount++;
obj.count++;
if (x >= MinTileX) {
x--
}
else {
if (y >= MinTileY) {
y--
x = MaxTileX
}
else {
return
}
}
traversal()
}
}
}
if (imageryProvider._readyError) {
progress[i] = {
value: itemTotalProgress
}
readyPromise()
return
}
imageryProvider.readyPromise.then(() => {
readyPromise()
}).catch((e) => {
imageryProvider._readyError = true
progress[i] = {
value: itemTotalProgress
}
readyPromise()
});
}
}
desist() {
this.state = false
}
}
}
export { ScreenShot, ScreenShotHD }