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}像素
输出进度
0% 100%
0%
` _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 }