I'm working on a webpage that will dynamically render SVG graphics based on user interaction. Once complete, I would like the user to be able to print the graphics only - not simply print the webpage they reside on and the SVG along with it, but just the SVG. Also, the printed version will ideally be drawn slightly differently than the onscreen browser version. Is this sort of thing possible with current browsers and SVG?
In Java, I can provide either a paint engine or a print engine to my applications drawing routine, and this handles the same problem simply. I'm a novice to SVG, however, and I can't determine whether some similar mechanism exists.
You can use jQuery. Assume you have your svg in a DIV(svgDiv) in the web page, include a print button that calls the following, where the root svg has an id=mySVG, to get width/height, or use the svgDiv width/height. This will print the view that is currently in the svg window.
//---print button---
var printSVG = function()
{
var popUpAndPrint = function()
{
var container = $('#svgDiv');
var width = parseFloat(mySVG.getAttribute("width"))
var height = parseFloat(mySVG.getAttribute("height"))
var printWindow = window.open('', 'PrintMap',
'width=' + width + ',height=' + height);
printWindow.document.writeln($(container).html());
printWindow.document.close();
printWindow.print();
printWindow.close();
};
setTimeout(popUpAndPrint, 500);
};
You can call window.print to start the printing process from javascript.
You can make the printed and visible versions different using media queries E.g.
#media print { different css for print SVG }
If you don't want existing stuff on the page to print, use the media query to set it display:none or visibility:hidden.
Related
I am setting up a specialised Print button. The page is complicated and needs some pre-processing before being sent to window.print().
I have the Highcharts code working at this point. It correctly resizes the charts on the page, and then, post print, it sizes them back to their original size.
The problem is that from then on, the charts will not respond to Media Query changes. The site is Responsive, built on Bootstrap, so this is not a functional result.
How do I change the chart size, but leave it able to respond to Media Queries?
The code I am using is:
Setup Code
var saveChartContainerWidth = $('.highcharts-container').css('width');
var saveChartContainerWidthSVG = saveChartContainerWidth.slice(0, -2);
$('.highcharts-container').css('width', '690px');
$(Highcharts.charts).each(function(i,chart){
var height = chart.renderTo.clientHeight;
var width = 690; // chart.renderTo.clientWidth;
chart.setSize(width, height);
chart.reflow();
});
Post Print Teardown Code
$('.highcharts-container').css('width', saveChartContainerWidth);
$(Highcharts.charts).each(function(i,chart){
var height = chart.renderTo.clientHeight;
var width = saveChartContainerWidthSVG;
chart.setSize(width, height);
chart.reflow();
});
With the help of #Ryan's link, and comments from a co-worker, I tried a number of solutions which, while not working, got me closer.
Having then a better idea of what to look for, I finally found this answer Highcharts + Bootstrap .table-responsive issue which provided a key ingredient.
The two keys are:
Do not set the size on either the SVG itself, or the direct Highchart's container. (I set it on a containing Div one level higher.)
Trigger a $(window).trigger("resize"); event.
This worked in all browsers tested (Firefox, Chrome, IE 9 - 11).
----------------- The Final Code -----------------------
// Setup
$('.chart-container').css('width', '690px');
$(window).trigger("resize");
// Teardown
$('.chart-container').css('width', '');
$(window).trigger("resize");
Do this after setting the size will do the trick.
window.onresize = () => {
chart.setSize($('parentElement').offsetWidth, height)
chart.reflow()
}
Yet if you change the onresize function to something else, it might not work. So this is more like a quick solution, yet it works perfectly
Can I use some sort of JS script to take advantage of the size control here in the url?
<iframe id="myIframe" src="https://media.embed.ly/1/frame?url=http%3A%2F%2Fwww.twitch.tv%2Fgamemode_mc_&width=1280&height=1280&secure=true&key=0202f0ddb5a3458aabf520e5ab790ab9&"
(My goal here is actually to place this Twitch feed as a background to my webpage - resizing the actual content of the iframe is actually a very unusual but additional treat here, because of the way Twitch's url works!)
To be clear, I'm very early in my learning of JS, and looking for a beginner solution to take the browser window size to dynamically control the parameters in this url to control the size of the content in this iframe.
width=1280&height=1280&
are the key lines here. I need to make these measurements follow the viewport size instead of being static. What method is best to do this?
You can certainly set the src to your iframe programmatically, and build the src url based on variables such as your viewport size.
You can try something like this:
function loadIframe() {
var url = '',
viewportWidth = document.documentElement.clientWidth,
viewportHeight = document.documentElement.clientHeight;
url = 'https://media.embed.ly/1/frame?url=http%3A%2F%2Fwww.twitch.tv%2Fgamemode_mc_&width=' + viewportWidth + '&height=' + viewportHeight + '&secure=true&key=0202f0ddb5a3458aabf520e5ab790ab9&';
document.getElementById('myIframe').src = url;
}
Then you can make the iframe reload when the window is resized and when the window is done loading:
window.onload = loadIframe;
window.onresize = loadIframe;
However I would actually recommend using jQuery to help you do this as you would be able bind to cross-browser events easier.
i have a php based site that needs to display images on the homepage that have arbitrary proportions. the requirement is to make them fill the browser window but to retain their aspect ratio.
for some reason i am having some trouble getting this to work using the jquery cycle plugin.
essentially the server-side code just pulls them from the db and pushes img elements into a div. i read the image sizes using php and write that to the alt element
then in my javascript code i have this:
$(document).ready(function() {
var window_h = $(window).height();
var window_w = $(window).width();
// sets the div that contains the jquery cycle images
$('#homepage-background-images').width(window_w);
$('#homepage-background-images').height(window_h);
$(window).resize(function() {
window_h = $(window).height();
window_w = $(window).width();
$('#homepage-background-images').width(window_w);
$('#homepage-background-images').height(window_h);
});
// homepage cycle
$('#homepage-background-images').cycle({
fx: 'fade',
speed: 5500,
fit: 1,
width: window_w,
height: window_h,
});
// ...
Obviously this isn't going to work since each image has a different aspect ratio, but I was wondering how one might pass serial aspect ratios into jquery cycle? These will always need to take the browser window size into consideration...
I have tried using the 'before' option on jquery, but it seems that you can't really affect the image properties there. I tried to use that to change the window_h variable based on a quick aspect ratio calculation but even updating that in my onBefore function seems to yield no result on the cycling images...
Any ideas? Is this tricky or am I just missing something obvious?
Thanks!
- J
If you use CSS max-width and max-height instance of HTML width and height it don't lose aspect ratio. Try adding style attribute to your image
I wrote a simple javascript code to load an image and alert its width and height, but I found its width and height will different between desktop and iPad.
For example, I load an image that size is 8000*1845, browser shows image width is 8000 and height is 1845. Therefore, on iPad, browser show image width is 2000 and height is 462.
The other image is 2600 * 2400, browser shows image width is 2000 and height is 2400, but it shows image width is 1300 and height is 1200.
I don't know whether I misunderstanding something or not. Will iOS downsize the image?
Anybody knows? Please tell me what happen?
var img8000 = new Image();
img8000.src = '8000_1845.jpg';
img8000.onload = function () {
alert(img8000.width + ' ' + img8000.height);
}
var img2600 = new Image();
img2600.src = '2600_2400.jpg';
img2600.onload = function () {
alert(img2600.width + ' ' + img2600.height);
}
When you get the image's height or width using this.width or when using jQuery's $(this).width() you are actually getting its current dimensions. If the image is scaled up or down, then the values you get will not match the actual source image's dimensions.
I made an example you can play with. It is pre-written to use onclick, but if you remove those onclick attributes and uncomment the jQuery code, you'll find it alerts the same values.
You should attempt to avoid image scaling by placing the image somewhere on the page where the CSS does not affect its size (as a test, try making a blank page containing just the image), and remove any custom height/width attributes if they exist.
Otherwise, if the scaling is done natively by the iPad Safari browser, there is little you can do.
We are using Mootools Multibox to display images.
The first time we view it with Chrome and Safari, the images are zoomed in and have scrollbars.
When we reload the page, the images display correctly without scrollbars.
What could be the cause of this?
How can we fix this so that the images are displayed with their correct sizes the first time viewed in Chrome and Safari?
in this block of code:
showContent: function(){
this.box.removeClass('MultiBoxLoading');
this.removeContent();
this.contentContainer = new Element('div', {
'id': 'MultiBoxContentContainer',
'styles': {
opacity: 0,
width: this.contentObj.width,
height: (Number(this.contentObj.height)+this.contentObj.xH)
}
}).inject(this.box,'inside');
it sets with width of the content box to the contentObj.width direct. which is fine if the browser has the image in the cache - at which point it will work but not so fine when it does not.
it uses Asset.js to load an image here:
load: function(element){
this.box.addClass('MultiBoxLoading');
this.getContent(element);
if(this.type == 'image'){
var xH = this.contentObj.xH;
this.contentObj = new Asset.image(element.href,{onload:this.resize.bind(this)});
this.contentObj.xH = xH;
}else{
this.resize();
};
},
the problem is, only after the onload fires does the browser know the actual width and height of the image (available through this.width / this.height if not bonund to class scope). although this will return an image object early (into contentObj), it probably shouldn't just yet and should do it after the onload fires. the onload here should be what injects the image into the container and sets width and height to host it. instead, it applies this.resize(image)
i hope this gives you some ideas as to how to refactor the class to make it work better.
ADDITONALLY: var xH = this.contentObj.xH; and this.contentObj.xH = xH; -> element storage for other elements direct into the object? this pre-dates mootools 1.2 which introduced closure based uid specific storage per element. bad practice, can cause slowness in IE, memory leaks etc.
refactor to this.contentObj.store("xH", something) with this.contentObj.retrieve("xH") to get it back