I am trying to print a large SVG chart from a browser, the SVG chart is embedded into the HTML. The width / height of the chart is set to absolute. The print only prints a part of the SVG chart, however much will fit on 1 page, and cuts the rest off. Is there a way to split up the chart to print into separate pages?
This totally depends on what browser you are using to view the SVG. Either try a different browser... Safari has GREAT printing capabilities (on the Mac at least).. or... "isolate" the SVG.. Either look at the source and figure out the relative URL to the embedded SVG and enter it into the URL bar..
<td><object id="object" type="image/svg+xml" data="**smiley.svg**">Please use a modern browser!</object></td>
<td><iframe id="iframe" src="**smiley.svg**">Please use a modern browser!</iframe></td>
<td><embed id="embed" src="**smiley.svg**" type="image/svg+xml" /></td>
<td><img id="img" alt="smiley face" src="**smiley.svg**" /></td>
or Copy and paste the actual SVG code from the inline source and paste it into a plain text document with the .svg extension...
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice"
style="width:100%; height:100%; position:absolute; top:0; left:0; z-index:-1;">
<linearGradient id="gradient">
<stop class="begin" offset="0%"/>
<stop class="end" offset="100%"/>
</linearGradient>
<rect x="0" y="0" width="100" height="100" style="fill:url(#gradient)" />
<circle cx="50" cy="50" r="30" style="fill:url(#gradient)" />
</svg>
Then you can use a multitude of applications, from Illustrator, to the free Inkscape, or MANY, many others to manipulate (or print) it to your hearts content.
Use phantomjs.org project to generate your chart images at server.
It allows to load any HTML page by URL into headless WebKit machine and render it into PNG.
Plus, you can get final size of your page and then cut it into peaces via defining Clip Region in cycle.
For example next sample exports several charts from the page into separate PNG images in file system. After that you can assemble your new web page or pack them into PDF and provide download link to your user. This would be the most reliable and stable printing solution for web application.
var page = require('webpage').create();
page.viewportSize = { width: 1280, height : 1024 };
page.open('http://chart.html', function () {
page.clipRect = page.evaluate(function () {
var chart = jQuery("#chart1");
return { top: chart.offset().top, left: chart.offset().left, width: chart.outerWidth(), height: chart.outerHeight() };
});
page.render('chart1.png');
page.clipRect = page.evaluate(function () {
var chart = jQuery("#chart2");
return { top: chart.offset().top, left: chart.offset().left, width: chart.outerWidth(), height: chart.outerHeight() };
});
page.render('chart2.png');
page.clipRect = page.evaluate(function () {
var chart = jQuery("#chart3");
return { top: chart.offset().top, left: chart.offset().left, width: chart.outerWidth(), height: chart.outerHeight() };
});
page.render('chart3.png');
phantom.exit();
});
Related
I've been working on PrimeFaces Bar chart model,and its getting on my nerves now,I just can't get how its setting chart series values.What expected result should be that One Open for say abc and one closed for xyz, But what It shows one open and one closed for xyz,ABC is Ignored. If I change the position of
barModel.addSeries(close);
barModel.addSeries(open);
to
barModel.addSeries(open);
barModel.addSeries(close);
Then It shows One open and one closed for only abc,Not xyz.
here's my getBarModel() first,
public BarChartModel getBarModel() {
barModel=new BarChartModel();
ChartSeries open = new ChartSeries();
open.setLabel("OPEN");
ChartSeries close = new ChartSeries();
close.setLabel("Close");
open.set("abc", 1);
close.set("xyz", 1);
barModel.addSeries(close);
barModel.addSeries(open);
barModel.setMouseoverHighlight(false);
barModel.setShowPointLabels(false);
barModel.setTitle("Incident_application");
barModel.setLegendPosition("ne");
barModel.setShowDatatip(false);
barModel.setShowPointLabels(true);
barModel.setExtender("chartExtender");
barModel.setSeriesColors("A2CC39,1B75BA");
Axis xAxis = barModel.getAxis(AxisType.X);
xAxis.setLabel("Applications");
barModel.setAnimate(true);
Axis yAxis = barModel.getAxis(AxisType.Y);
yAxis.setLabel("No. of Incident");
yAxis.setMin(0);
yAxis.setMax(20);
yAxis.setTickInterval("10");
return barModel;
}
and here is xhtml
<h:outputScript library="primefaces" name="jquery/jquery.js" target="head" />
<h:outputScript library="primefaces" name="jquery/jquery-plugins.js" target="head" />
<style type="text/css">
table.jqplot-table-legend {
border: none;
font-size: x-large;
}
div.jqplot-table-legend-swatch
{
width: 2vw;
height: 2vh;
}
div.jqplot-gridData{
display:none;
}
div.jqplot-xaxis-tick{
font-weight:bold !important;
}
.jqplot-axis.jqplot-xaxis{
font-weight:bold;
}
.jqplot-point-label {
font-size: 300%;
color: black;
font-weight: bold;
}
.jqplot-target{
color:black !important;
}
</style>
<script>
function chartExtender() {
this.cfg.grid = {
background: 'transparent',
gridLineColor: '#303030',
drawBorder: false,
};
}
</script>
<h:form id="barChart">
<p:chart id="bar" type="bar" model="#{incidentBarChartController.barModel}" />
<p:poll interval="10" global="false" update="barChart"/>
</h:form>
</h:body>
Snapshots of expected and Actual results are added below.
Expected Result
Actual Result
Edit
After adding
open.set("abc", 1);
open.set("xyz",0);
close.set("xyz", 1);
close.set("abc", 0);
I still get weird results i.e.
1 open and 1 closed for xyz and 0 open and 0 closed for xyz.
The only solution is that you as a developer make sure all series contains all keys and populate the keys which you do not have and make sure all keys in all series are in the same order.
The reason for this is that only you know the real order (that is why a LinkedHashMap is used in the series). jQplot or PrimeFaces cannot know this. If e.g. the first series misses a key and that series is used as the 'primary' to iterate over, where is the missing key going to put. And if e.g. at position 6, both have a key that is not in the other set, which one should be taken first? The jqPlot or PrimeFaces cannot know. All reasons that you as a developer should make sure it is explicit by putting all keys in all series.
I want to upload image in asp.net mvc like this way.I am using input type file for uploading images , its working fine but I want that when user click on this image and select that image , that image would appear on this type of box , how would I do that . I am saving images path in database and putting them on file directory.
I suspect the best bet is to use the HTML5 file API to read the contents of the attached image to display a preview. When the user submits the file you could do the server-side processing as you currently are, store the URL and return to the browser the location of the new image for proper preview. But check the performance of previewing a large image.
The link shows an example of previewing the file. I've copied the code in here as well, but please check the article for better understanding.
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'
].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
.thumb {
height: 75px;
border: 1px solid #000;
margin: 10px 5px 0 0;
}
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
I have a YouTube video embedded on our website and when I shrink the screen to tablet or phone sizes it stops shrinking at around 560px in width. Is this standard for YouTube videos or is there something that I can add to the code to make it go smaller?
You can make YouTube videos responsive with CSS. Wrap the iframe in a div with the class of "videowrapper" and apply the following styles:
.videowrapper {
float: none;
clear: both;
width: 100%;
position: relative;
padding-bottom: 56.25%;
padding-top: 25px;
height: 0;
}
.videowrapper iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
The .videowrapper div should be inside a responsive element. The padding on the .videowrapper is necessary to keep the video from collapsing. You may have to tweak the numbers depending upon your layout.
If you are using Bootstrap you can also use a responsive embed. This will fully automate making the video(s) responsive.
http://getbootstrap.com/components/#responsive-embed
There's some example code below.
<!-- 16:9 aspect ratio -->
<div class="embed-responsive embed-responsive-16by9">
<iframe class="embed-responsive-item" src="..."></iframe>
</div>
<!-- 4:3 aspect ratio -->
<div class="embed-responsive embed-responsive-4by3">
<iframe class="embed-responsive-item" src="..."></iframe>
</div>
Refined Javascript only solution for YouTube and Vimeo using jQuery.
// -- After the document is ready
$(function() {
// Find all YouTube and Vimeo videos
var $allVideos = $("iframe[src*='www.youtube.com'], iframe[src*='player.vimeo.com']");
// Figure out and save aspect ratio for each video
$allVideos.each(function() {
$(this)
.data('aspectRatio', this.height / this.width)
// and remove the hard coded width/height
.removeAttr('height')
.removeAttr('width');
});
// When the window is resized
$(window).resize(function() {
// Resize all videos according to their own aspect ratio
$allVideos.each(function() {
var $el = $(this);
// Get parent width of this video
var newWidth = $el.parent().width();
$el
.width(newWidth)
.height(newWidth * $el.data('aspectRatio'));
});
// Kick off one resize to fix all videos on page load
}).resize();
});
Simple to use with only embed:
<iframe width="16" height="9" src="https://www.youtube.com/embed/wH7k5CFp4hI" frameborder="0" allowfullscreen></iframe>
Or with responsive style framework like Bootstrap.
<div class="row">
<div class="col-sm-6">
Stroke Awareness
<div class="col-sm-6>
<iframe width="16" height="9" src="https://www.youtube.com/embed/wH7k5CFp4hI" frameborder="0" allowfullscreen></iframe>
</div>
</div>
Relies on width and height of iframe to preserve aspect ratio
Can use aspect ratio for width and height (width="16" height="9")
Waits until document is ready before resizing
Uses jQuery substring *= selector instead of start of string ^=
Gets reference width from video iframe parent instead of predefined element
Javascript solution
No CSS
No wrapper needed
Thanks to #Dampas for starting point.
https://stackoverflow.com/a/33354009/1011746
I used the CSS in the accepted answer here for my responsive YouTube videos - worked great right up until YouTube updated their system around the start of August 2015. The videos on YouTube are the same dimensions but for whatever reason the CSS in the accepted answer now letterboxes all our videos. Black bands across top and bottom.
I've tickered around with the sizes and settled on getting rid of the top padding and changing the bottom padding to 56.45%. Seems to look good.
.videowrapper {
position: relative;
padding-bottom: 56.45%;
height: 0;
}
#magi182's solution is solid, but it lacks the ability to set a maximum width. I think a maximum width of 640px is necessary because otherwhise the youtube thumbnail looks pixelated.
My solution with two wrappers works like a charm for me:
.videoWrapperOuter {
max-width:640px;
margin-left:auto;
margin-right:auto;
}
.videoWrapperInner {
float: none;
clear: both;
width: 100%;
position: relative;
padding-bottom: 50%;
padding-top: 25px;
height: 0;
}
.videoWrapperInner iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<div class="videoWrapperOuter">
<div class="videoWrapperInner">
<iframe src="//www.youtube.com/embed/C6-TWRn0k4I"
frameborder="0" allowfullscreen></iframe>
</div>
</div>
I also set the padding-bottom in the inner wrapper to 50 %, because with #magi182's 56 %, a black bar on top and bottom appeared.
Modern simple css solution
The new aspect-ratio is the modern solution to this problem.
aspect-ratio: 16 / 9;
That's all you need to make a div, image, iframe size automatically. Samples.
It's got good support, but is not yet in Safari (will be for upcoming iOS15) - so for now you'll still need to use a fallback. You can achieve that with the #supports feature
.element
{
aspect-ratio: 16 / 9;
#supports not (aspect-ratio: 16 / 9)
{
// take your pick from the other solutions on this page
}
}
Assuming your development browser does support this property be sure to test without it by commenting out both aspect-ratio and #supports.
This is old thread, but I have find new answer on https://css-tricks.com/NetMag/FluidWidthVideo/Article-FluidWidthVideo.php
The problem with previous solution is that you need to have special div around video code, which is not suitable for most uses. So here is JavaScript solution without special div.
// Find all YouTube videos - RESIZE YOUTUBE VIDEOS!!!
var $allVideos = $("iframe[src^='https://www.youtube.com']"),
// The element that is fluid width
$fluidEl = $("body");
// Figure out and save aspect ratio for each video
$allVideos.each(function() {
$(this)
.data('aspectRatio', this.height / this.width)
// and remove the hard coded width/height
.removeAttr('height')
.removeAttr('width');
});
// When the window is resized
$(window).resize(function() {
var newWidth = $fluidEl.width();
// Resize all videos according to their own aspect ratio
$allVideos.each(function() {
var $el = $(this);
$el
.width(newWidth)
.height(newWidth * $el.data('aspectRatio'));
});
// Kick off one resize to fix all videos on page load
}).resize();
// END RESIZE VIDEOS
If you are using Bootstrap 5.0, you can use .ratio
https://getbootstrap.com/docs/5.0/helpers/ratio/
Example
<div class="ratio ratio-16x9">
<iframe src="https://www.youtube.com/embed/zpOULjyy-n8?rel=0" title="YouTube video" allowfullscreen></iframe>
</div>
With credits to previous answer https://stackoverflow.com/a/36549068/7149454
Boostrap compatible, adust your container width (300px in this example) and you're good to go:
<div class="embed-responsive embed-responsive-16by9" style="height: 100 %; width: 300px; ">
<iframe class="embed-responsive-item" src="https://www.youtube.com/embed/LbLB0K-mXMU?start=1841" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0"></iframe>
</div>
Okay, looks like big solutions.
Why not to add width: 100%; directly in your iframe. ;)
So your code would looks something like <iframe style="width: 100%;" ...></iframe>
Try this it'll work as it worked in my case.
Enjoy! :)
I make this with simple css as follows
HTML CODE
<iframe id="vid" src="https://www.youtube.com/embed/RuD7Se9jMag" frameborder="0" allowfullscreen></iframe>
CSS CODE
<style type="text/css">
#vid {
max-width: 100%;
height: auto;
}
I am developing an iPad application with Phonegap and jQuery mobile. One of the functions required is to allow the user of the app to sign (their signature) in 2 boxes. I am using easel.js to handle the "drawing" on the canvas element.
The HTML structure of this page is something like:
<div class="signature-wrapper sw1">
<canvas class="flexBox" id="myCanvas" width="240" height="240"></canvas>
</div>
<div class="signature-wrapper sw2">
<canvas class="flexBox" id="myCanvas2" width="240" height="240"></canvas>
</div>
Where the 2 canvas elements are where the signatures will be drawn. Below each of these elements are buttons to clear and save each of the elements. When clicked, they fire functions to clear the canvas, or save the canvas to an image (the image is then placed over the canvas, and removed on clear)
The save functionality looks something like:
function saveStage1(){
var canvas = document.getElementById("myCanvas");
var imageData = canvas.toDataURL("image/png");
$('.sw1').append("<img src='" + imageData +"' style='position: absolute; left: 0px; top: 0px;' />");
}
Basically, it is just getting the content of the canvas and saving it to a PNG image, which is then appended to the wrapper for the canvas elements. There is additional code I have left out of the code here for clarity, dealing with localStorage and db.transactions.
This function is working as expected.
The next function is to clear the canvas:
function clearStage1(){
oldMidX, oldMidY, oldX, oldY = null;
delete window.currentShape;
stage.clear();
stage.removeAllChildren();
stage.update();
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
};
imageObj.src = 'images/signature-client.png';
$('.sw1 img').remove();
}
This clears the canvas, nulls some variables, and recreates the canvas.
This works 100% in chrome and safari, but does not work correctly on iPad as a Phonegap application. On iPad, you can draw, but once you have clicked save or clear you are unable to draw without navigating away and back to the screen. It seems there is a JavaScript error somewhere on the page on both the save and clear functions which is preventing any further JavaScript from executing without "reloading" the page.
I have setup my console in Safari on mac to look at xcode application, and there is no error in the log. Any help would be appreciated.
Can you superimpose canvas over video in IOS safari (IPAD)?
I tried adding text to the canvas but it does not show up on top of the video playing.
ON SAfari desktop it just works fine.
video_dom.addEventListener('play', function() {
ctx_overlay.font = "bold 16px sans-serif";
ctx_overlay.fillStyle="black";
ctx_overlay.fillText("Video1 Video1 Video1", 200, 225);
}, false);
<video id="video-canvas-fancy" loop autoplay loop height="640" width="965" style="position:absolute; top: 5; left: 5;">
<source src="http://severe-fire-901.heroku.com/videos/home.m3u8">
</video>
<canvas id="canvas-overlay" height="640" width="965" style="position:absolute; top: 10; left: 10;">
</canvas>
Please give more details or a code example in the future.
You mean <video>? With absolute positioning you should be able to put anything over it.
If you can't for some (buggy) reason on IOS, you can always use a <canvas> to render the video (call context.drawImage(video,0,0) every x frames per second) and then either render stuff on top of that or on top of a second canvas.