Im trying to animate 360 degree spin on a page using lot of images (110) with the spritespin bundle, which means that they are all loaded so that means the page take some time to be viewable. I tried preloading only one frame but then when I spin the picture around some frames dont load correctly (i get white spaces instead), especially on the last frame (so most likely the last frame still did not load).
So this is my spritespin config:
<script>
var frames = SpriteSpin.sourceArray('/images/RcH_png_000{frame}.jpg', {
frame: [1, 110]
});
$(".spritespin").spritespin({
// path to the source images.
source: frames,
//width : 480, // width in pixels of the window/frame
//height : 327, // height in pixels of the window/frame
responsive: true,
animate: false,
preloadCount:1,
plugins: [
'360', // display plugin
'drag', // interaction plugin
]
});
</script>
You can also check how the website is slowly loading here:
https://dry-cove-88007.herokuapp.com
var frames = SpriteSpin.sourceArray('/images/RcH_png_000{frame}.jpg', {
frame: [1, 110]
});
//add img
let imgLoading = $('<span class="loadersprite"><img src="/images/loading.gif"></span>');
imgLoading.insertAfter('.spritespin');
and then in the oncomplete method
$(".spritespin").spritespin({
source: frames,
//width : 480, // width in pixels of the window/frame
//height : 327, // height in pixels of the window/frame
responsive: true,
animate: false,
preloadCount:1,
plugins: [
'360', // display plugin
'drag', // interaction plugin
],
onComplete:function(){
imgLoading.hide();
}
});
Related
I am building a webpage which includes a Gridstack grid. I initialise it like this:
<script type="text/javascript">
var grid = GridStack.init({
acceptWidgets: false, // Accept widgets from other grids or from outside.
alwaysShowResizeHandle: true, // Should resize handle be visible at all times or only at hover.
animate: false, // ???
auto: true, // Should Gridstack automaticaly initialize it's items?
cellHeight: "155px", // One cell height.
column: 48, // Number of columns to which to snap to.
disableDrag: false, // Eanble or disable dragging.
disableOneColumnMode: true, // Disable "one-column" mode when width equals minimal width.
disableResize: false, // Enable or disable resizing.
draggable: true, // ???
dragOut: true, // Prevent dragging items outside of their parent element.
float: true, // Enable floating tiles.
handle: '.grid-stack-item-content', // Select draggable handle class.
handleClass: 'grid-stack-item-content', // Select draggable handle class (override).
itemClass: 'grid-stack-item', // Choose class, which will be treated as a tile.
maxRow: 12, // Maximum rows where zero means unlimited.
minRow: 1, // Minimum rows to prevent empty grid from colapsing.
minWidth: 768, // Constant width which determines, when "one-column" mode is triggered.
oneColumnDomSort: false, // ???
placeholderClass: 'grid-stack-placeholder', // Select placeholder class.
placeholderText: '', // Text inside a placeholder.
resizable: { // Should resize handle be visible at all times or only at hover (override).
autoHide: false,
handles: 'n, nw, w, sw, s, se, e, ne'
},
removeable: false, // Enables removing of tiles if they are dragged outside of the grid.
removeTimeout: 2000, // Time in "ms" before tiles dragged out of the grid are removed.
row: 48, // Fixed number of rows where zero means unlimited.
rtl: false, // Right to left mode.
staticGrid: false, // Prevent any kind of resizing or drag & drop functionalities.
verticalMargin: 20, // Vertical gap between tiles.
});
</script>
And then I dynamicaly create a widget i.e. tile, using:
<!-- Gridstack: Example of adding a tile i.e. widget -->
<script>
grid.addWidget(`
<div>
<div class="grid-stack-item-content">
<p>...</p>
</div>
</div>`,
0,0,1,1,true,1,48,1,48,"ID");
</script>
This creates the widget in Chromium, Firefox, Edge. But not in IE11. Does anyone know what could I be doing wrong? It looks like I am doing all by the manual...
This is the console log in IE11:
And if I click on the error I get this line, where there seems to be no weird characters:
I'd like to set an image of a map - or, better yet, a generated map - on the x-z plane of a high-charts graph. Is there a way to do this with background image? I understand you can set the color of the back, bottom, and side frame, is there any way to set images for those frames?
You can use SVG <pattern> element with <image> added inside of it, and set the chart.options3d.frame.bottom.color equal to this pattern, just like that:
First you need to create new pattern basing on current dimensions of mentioned frame. The best place to implement it, should be the chart.events.load function:
chart: {
events: {
load() {
var chart = this
var frameBottomDim = chart.frameShapes.bottom.element.getBBox()
var defs = document.querySelectorAll('defs')[0]
var pattern = chart.renderer.createElement('pattern')
var img = chart.renderer.createElement('image')
pattern.attr({
"patternUnits": "userSpaceOnUse",
"x": frameBottomDim.x,
"y": frameBottomDim.y,
"width": frameBottomDim.width,
"height": frameBottomDim.height,
"id": "frameBg",
})
img.attr({
"href": "https://static.makeuseof.com/wp-content/uploads/2010/03/clouds-1-670x335.jpg",
"width": frameBottomDim.width,
"height": frameBottomDim.height,
preserveAspectRatio: 'none'
})
img.add(pattern)
pattern.add(this.renderer.defs)
}
}
}
Then set the frame color property to url(#[pattern_name]):
options3d: {
enabled: true,
alpha: 10,
beta: 20,
depth: 400,
frame: {
bottom: {
color: 'url(#frameBg)'
}
}
}
Live example: https://jsfiddle.net/h8tv4xpg/
Web API Reference: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/pattern
I'm trying to render a report via PhantomJS 2.1.1 where the HTML page contains a chart generated by Chart.js. I have full control over that page. The resulting PDF should be a printable A4. As you can see in the screenshot down below, the chart is very blurry.
Is there any way I can make either Chart.js or PhantomJS render the chart/page at a higher DPI so that the drawn canvas appears nice and sharp?
PhantomJS:
page.property('paperSize', {
format: 'A4',
orientation: 'portrait',
border: '2cm'
});
Chart.js:
var lineChart = new Chart(ctx).Line(data, {
animation: false,
responsive: true,
pointDot: false,
scaleShowLabels: true,
showScale: true,
showTooltips: false,
bezierCurve : false,
scaleShowVerticalLines: false
});
Add viewportSize and zoomFactor in your phantomjs page:
await page.property('viewportSize', { height: 1600, width: 3600 });
await page.property('zoomFactor', 4);
and add in your html head template
<script>
window.devicePixelRatio = 4;
</script>
Try setting the zoom factor using a higher DPI for paper in relation to screen DPI:
page.zoomFactor = 300 / 96; // or use / 72
Must be set after page size is defined.
You could also check out this answer:
Poor quality of png images drawn into html canvas
For Phantom 2, I rendered the charts with a large canvas to get the resolution up and then converted it into a png finally destroying and removing the old canvas and replacing them with an image with responsive CSS classes. Adjusting the knobes on the canvas width and height in addition to Chart.js options will get you a perfect render. We were able to get our rendering speed up with the approach (alternative to SVG renders) and the file size down.
HTML:
<div class="container">
<!-- generated images -->
<img id="someIdImage" class="img-responsive"></img>
<!-- temporary canvas -->
<canvas id="someId" width="2000" height="600"></canvas>
</div>
Javascript:
/**
* _plot() plot with Chart.js
*
* #param {Function} callback
*/
function _plot(callback) {
var config = {}; // some Chart.js config
var id = 'someId';
var el = document.querySelector('#' + id);
var el2d = el.getContext('2d');
// plot instance
var instance = new Chart(el2d, config);
// generate and append image
document.querySelector('#' + id + 'Image').setAttribute('src', el.toDataURL('image/png'));
// destroy instance
instance.destroy();
el.parentElement.removeChild(el);
// callback
if (callback) {
callback();
}
}
Chart.js now has the parameter "devicePixelRatio". This allows you to increase the resolution directly in Chart.js. (normal 96dpi. target 300dpi; 300/96 = 3.125)
options:{
devicePixelRatio: 3
}
Documentation: https://www.chartjs.org/docs/3.0.2/configuration/device-pixel-ratio.html
I can confirm that the #DevTrong response is working with Phantomjs 2.1.1
the only difference is that i set in my settings file:
page.viewportSize = { width: 3600, height: 1600 };
page.zoomFactor = 4;
Note: Its very important to set in you html this part:
<//script>
window.devicePixelRatio = 4;
<//script> (fix the script tag)
I have a web page that is loading images and scans across about 600+ images as the user presses next or previous. This is working fine. However, the image load time is slow so the idea is to put a processing while in place of the images until they are fully loaded. I can get the processing wheel to load perfectly fine but I cannot get it to hide once the image or document is loaded. I have tried doing this two different ways:
Attempt 1:
$('#centerImage').ready(function () {
$('.spinner').css('display', 'none');
});
Attempt 2:
$('#centerImage').ready(function () {
$('.spinner').hide();
});
I have also tried replacing the selector #centerImage on the .ready() function with document but still don't see the Processing Wheel get hidden.
What I find strange is that when I try and hide an ID instead of a Class, it works perfectly fine. I tried a 'Try Me' on W3 Schools with a simple example and hiding a class with the .hide() doesn't work there either.
Google isn't returning anything specific to any limitations with jQuery hiding classes. Is this possible or am I approaching this the wrong way?
NOTE: I'm using spin.js for the processing wheel.
All Code:
JavaScript:
EDIT: Added .load instead of .ready
var previousImage = document.getElementById("previousImage");
var centerImage = document.getElementById("centerImage");
var nextImage = document.getElementById("nextImage");
previousImage.setAttribute("src", "../.." + document.getElementById("MainContent_lblPreviousImage").innerHTML);
centerImage.setAttribute("src", "../.." + document.getElementById("MainContent_lblCenterImage").innerHTML);
nextImage.setAttribute("src", "../.." + document.getElementById("MainContent_lblNextImage").innerHTML);
$('#centerImage').load(function () {
$('.spinner').hide();
});
HTML/ASP.NET:
<div id="images">
<img id="previousImage" onload="showProgress()" alt="" src=""/>
<img id="centerImage" onload="showProgress()" alt="" src=""/>
<img id="nextImage" onload="showProgress()" alt="" src=""/>
</div>
Show Progress JavaScript File:
function showProgress () {
var opts = {
lines: 13, // The number of lines to draw
length: 20, // The length of each line
width: 10, // The line thickness
radius: 30, // The radius of the inner circle
corners: 1, // Corner roundness (0..1)
rotate: 0, // The rotation offset
direction: 1, // 1: clockwise, -1: counterclockwise
color: '#000', // #rgb or #rrggbb or array of colors
speed: 1, // Rounds per second
trail: 60, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false, // Whether to use hardware acceleration
className: 'spinner', // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: '50%', // Top position relative to parent
left: '50%' // Left position relative to parent
};
var target = document.getElementById('images');
var spinner = new Spinner(opts).spin(target);
}
Thanks in advance for any helpful input.
As #Barmar $("#centerimage").ready() is the same as $(document).ready(). There's no separate ready event for each element, it just applies to the whole DOM.
Ready is used to check if the DOM is ready and the load is used to check if the Content is loaded.
Use load instead of ready:
$('#centerImage').load(function () {
I'm using spin.js ( http://fgnass.github.com/spin.js/) while a large full width/height image loads. The problem is I'm having trouble stopping the spinner. The stop() method doesn't seem to work. There's what I've got:
$(document).ready(function($) {
var img = new Image();
img.src = $('#top-bg').css('background-image').replace(/url\(|\)/g, '');
img.onload = function(){
$("#top-bg").spinner.stop();
$(".top-bar").delay(1500).fadeIn(5000);
$("#arrow, #arrowrt, #top-icons").delay(5000).fadeIn(5000);
};
});
I also tried
.spin(false)
and
.data('spinner').stop()
This is the spinner settings:
$(document).ready(function($) {
var opts = {
lines: 9, // The number of lines to draw
length: 11, // The length of each line
width: 4, // The line thickness
radius: 10, // The radius of the inner circle
rotate: 0, // The rotation offset
color: '#fff', // #rgb or #rrggbb
speed: 0.9, // Rounds per second
trail: 54, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false, // Whether to use hardware acceleration
className: 'spinner', // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: 'auto', // Top position relative to parent in px
left: 'auto' // Left position relative to parent in px
};
var target = document.getElementById('top-bg');
var spinner = new Spinner(opts).spin(target);
});
You need to store the spinner instance somewhere - in a way that you can access it when you need it to stop the spinning:
var spinner = new Spinner(opts).spin(target);
$(target).data('spinner', spinner);
And now you're able to stop it like this:
$('#top-bg').data('spinner').stop();
You can stop spinner without instance:
$(target).spin(false);
This seems to work across browsers and uses less code:
$(".spinner").remove();
Remove all DOM of containter, example:
<style type="text/css">.loader{ display: none; }</style>
<div>
<span class="loader"></span>
<span>Foo</span>
</div>
If need apply sping append it in
$('.loader').show().spin();
And destroy:
$('.loader').hide().empty();
Remember, jQuery.empty() automaticaly remove all DOM of object before destroy.