From 2ec2d0a7d137564f874339f71ce35114362e5b13 Mon Sep 17 00:00:00 2001 From: jrobinso <933148+jrobinso@users.noreply.github.com> Date: Fri, 2 Aug 2024 19:18:01 -0700 Subject: [PATCH] Support save to png --- js/browser.js | 64 ++++++++++++++++++++++----------------- js/trackViewport.js | 4 +-- js/ui/saveImageControl.js | 2 +- package.json | 1 - 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/js/browser.js b/js/browser.js index 519c918d8..46a3107dc 100755 --- a/js/browser.js +++ b/js/browser.js @@ -1,5 +1,4 @@ import $ from "./vendor/jquery-3.3.1.slim.js" -import html2canvas from '../node_modules/html2canvas/dist/html2canvas.esm.js' import {BGZip, FileUtils, igvxhr, StringUtils, URIUtils} from "../node_modules/igv-utils/src/index.js" import * as DOMUtils from "./ui/utils/dom-utils.js" import {createIcon} from "./ui/utils/icons.js" @@ -418,19 +417,13 @@ class Browser { toSVG() { const {x, y, width, height} = this.columnContainer.getBoundingClientRect() - - const h_render = 8000 - + const h_render = height const config = { - width, height: h_render, - backdropColor: 'white', - multiLocusGap: 0, - viewbox: { x: 0, @@ -438,7 +431,6 @@ class Browser { width, height: h_render } - } const context = new C2S(config) @@ -452,26 +444,14 @@ class Browser { // ROI -> SVG delta.deltaX = x this.roiManager.renderSVGContext(context, delta) - - // reset height to trim away unneeded svg canvas real estate. Yes, a bit of a hack. - context.setHeight(height) - return context.getSerializedSvg(true) - - } - - renderSVG($container) { - const svg = this.toSVG() - $container.empty() - $container.append(svg) - - return svg } saveSVGtoFile(config) { let svg = this.toSVG() + // For testing if (config.$container) { config.$container.empty() config.$container.append(svg) @@ -480,16 +460,46 @@ class Browser { const path = config.filename || 'igvjs.svg' const data = URL.createObjectURL(new Blob([svg], {type: "application/octet-stream"})) FileUtils.download(path, data) + URL.revokeObjectURL(data) } - savePNGtoFile(filename) { - html2canvas(this.columnContainer, {allowTaint: true}).then(canvas => { - const path = filename || 'igvjs.png' - const data = canvas.toDataURL('image/png') - FileUtils.download(path, data) + savePNGtoFile({filename}) { + + const svgAsString = this.toSVG() + + const svgBlob = new Blob([svgAsString], { + type: 'image/svg+xml' }) + const svgObjectUrl = URL.createObjectURL(svgBlob) + + const img = document.createElement('img') + + const onImageLoaded = () => { + + const dimensions = this.columnContainer.getBoundingClientRect() + const devicePixelRatio = window.devicePixelRatio + const w = dimensions.width * devicePixelRatio + const h = dimensions.height * devicePixelRatio + const canvas = document.createElement('canvas') + canvas.width = w + canvas.height = h + const context = canvas.getContext('2d') + context.scale(devicePixelRatio, devicePixelRatio) + + context.drawImage(img, 0, 0) + const data = canvas.toDataURL("image/png") + filename = filename || 'igvjs.png' + FileUtils.download(filename, data) + + + // Here the image is ready to use, e.g., document.body.appendChild(createdImage); + URL.revokeObjectURL(svgObjectUrl) + } + img.addEventListener('load', onImageLoaded) + img.src = svgObjectUrl } + /** * Initialize a session from an object, json, or by loading from a file. * diff --git a/js/trackViewport.js b/js/trackViewport.js index 569d99dce..80b675a4e 100644 --- a/js/trackViewport.js +++ b/js/trackViewport.js @@ -473,9 +473,7 @@ class TrackViewport extends Viewport { const y = deltaY + this.contentTop const yClipOffset = -this.contentTop - if (context.saveWithTranslationAndClipRect) { - context.saveWithTranslationAndClipRect(id, x, y, width, height, yClipOffset) - } + context.saveWithTranslationAndClipRect(id, x, y, width, height, yClipOffset) let {start, bpPerPixel} = this.referenceFrame diff --git a/js/ui/saveImageControl.js b/js/ui/saveImageControl.js index d9d0b616c..243623e07 100644 --- a/js/ui/saveImageControl.js +++ b/js/ui/saveImageControl.js @@ -62,7 +62,7 @@ class SaveImageControl extends NavbarButton { { label: "Save as PNG", click: e => { - this.browser.savePNGtoFile(undefined) + this.browser.savePNGtoFile({}) this.dropdown.dismiss() } }, diff --git a/package.json b/package.json index b74830704..8fe1effa2 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "dompurify": "^3.0.9", "eslint": "^6.4.0", "hdf5-indexed-reader": "github:jrobinso/hdf5-indexed-reader#v0.5.6", - "html2canvas": "^1.4.1", "igv-utils": "github:igvteam/igv-utils#v1.5.9", "mocha": "^10.2.0", "rollup": "^2.66.0",