Split oversized images when exporting to PDF - javascript

I am using pdfmake after html2canvas. I am turning a big chunk of html to image (canvas) and then this into pdf (because of very complicated styling in this html).
In case the canvas is longer than 1 page, I wish to show as much as I can on the 1st page, then on the 2nd to continue from where I stopped and etc. etc.
I was thinking of something like this:
var dd = {
content: [
{
image: 'sampleImage.jpg',
height: 1500,
width: 500,
margin: [0, 0, 0, 0]
},
{
image: 'sampleImage.jpg',
height: 1500,
width: 500,
margin: [0, -820, 0, 0]
}
]
}
Expecting:
1st page: Part of the image (as much as it fits in 1 page)
2nd page: Different part of image (starting from where page 1 finished)
Result:
1st correct, 2nd page identical to 1st!
Surprisingly when I tried:
var dd = {
content: [
{
image: 'sampleImage.jpg',
height: 1500,
width: 500,
margin: [0, -820, 0, 0]
},
{
image: 'sampleImage.jpg',
height: 1500,
width: 500,
margin: [0, 0, 0, 0]
}
]
}
Expecting:
2nd page: Part of the image (as much as it fits in 1 page)
1st page: Different part of image (starting from where page 1 finished)
Result:
Both pages correct but... wrong order!

Related

Is it possible to make img hover overlay with macyjs?

Im building my first website and currently struggle with making img overlay on hover in my gallery.
I've made masonry layout using macyjs and can't get my css right to make an overlay.
This is also my first post here so If I did screw something up with the code snippet, sorry in advance :)
const msnry = new Macy({
container: '.image-grid',
mobileFirst: true,
columns: 1,
breakAt: {
400: 2,
700: 3,
1100: 4,
},
margin: {
x: 20,
y: 20,
},
});

Chain Multiple Elements In HTML2PDF?

I have a page that looks like this: https://www.pdffiller.com/jsfiller-desk16/?isShareViaLink=1&requestHash=0b686d3412abda4ce3280790c21ed048547fe38efb37cfe5eedfc9ab11dc5674&lang=en&projectId=1109967956&loader=tips&MEDIUM_PDFJS=true#9d3d7d408e8045169526ca212483a79f
[Sorry for the long link]
Sadly, I cannot save the PDF so I am trying to print every page. Each page has a div element with a [data-page-id="0"] wjere id=0 is the page number, starting from 0.
I have a sample script here
async function testShot() {
var element = document.querySelector(`div[data-page-id="0"]`);
await html2pdf(element, {
margin: 0,
width: "1442px",
html2canvas: {
scale: 1,
height: element.offsetHeight,
width: element.offsetWidth,
},
height: "1866.12px",
filename: "test.pdf",
image: { type: "png", quality: 0.98 },
});
}
And it works but how can I chain this for multiple elements into 1 pdf?

intersectionObserver only fires once

I'm attempting to use the new Intersection Observer API, but I can only get to fire its event just once. I believe I'm using it correctly, as I'm using the MDN example almost verbatim.
https://jsfiddle.net/bukzor/epuwztn0/106/
function startObserver() {
// Almost verbatim from MDN docs:
// https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
let options = {
root: document.querySelector('#svg'),
rootMargin: '0px',
threshold: 0.50,
}
let observer = new IntersectionObserver(onIntersection, options);
let target = document.querySelector('circle');
observer.observe(target);
}
function onIntersection(entries, observer) {
// Simply log all intersectiono entries.
console.log(observer)
console.log("intersections:")
entries.forEach(function(entry) {
console.log(entry)
// This code is just a wild guess, but it still won't fire a second time.
observer.observe(entry.target)
})
}
When I run it, I get just one entry in the console and never another. The zero-size rectangles it mentions, and the isVisible: false seem like additional symptoms, but I haven't been able to find the cause.
IntersectionObserver {root: svg#svg, rootMargin: "0px 0px 0px 0px", thresholds: Array(1), delay: 0, trackVisibility: false}
intersections:
IntersectionObserverEntry {time: 550.8100000151899, rootBounds: DOMRectReadOnly, boundingClientRect: DOMRectReadOnly, intersectionRect: DOMRectReadOnly, isIntersecting: false, …}
time: 550.8100000151899
rootBounds: DOMRectReadOnly {x: 0, y: 0, width: 0, height: 0, top: 0, …}
boundingClientRect: DOMRectReadOnly {x: 0, y: 0, width: 0, height: 0, top: 0, …}
intersectionRect: DOMRectReadOnly {x: 0, y: 0, width: 0, height: 0, top: 0, …}
isIntersecting: false
intersectionRatio: 0
target: circle
isVisible: false
What's more, I believe the API itself is working fine on my browser, because this demo works fine (below). It's actually quite similar to my example.
http://szager-chromium.github.io/IntersectionObserver/demo/svg/
What am I doing wrong?

How to add slideWidth into a breakpoint in Glide.js

I have to set the slide width to a specific size if the viewport is between a range.
breakpoints: {
767: {
perView: 1,
peek: 193,
slideWidth: 277
},
1023: {
perView: 1,
peek: 212,
}
}
The documentation states that you can use slideWidth in the settings, so I'm assuming is in the breakpoints, but there's no example on how to do that and I haven't found an example of it.
The whole interface is responsive, so even if slideWidth is working behind the scenes, the width of the slide changes no matter what.
I also tried with pure CSS but Glide takes charge of course and overwrites when a resize event occurs. Also tried with pure JS and measuring the viewport myself, but again Glide.js takes charge and the interface is being offset, so the slide moves a bit and doesn't match the screen.
Here is a codepen on how to use the breakpoints https://codepen.io/tfoh/pen/zjqzZo
new Glide('#glide1', {
type: 'carousel',
perView: 3,
breakpoints: {
800: {
perView: 1
}
}
}).mount();
I manage that with css, this example make width of slides the same on any resolution, .glide-wrapper you should add manually like a glider parent div
.glide-wrapper {
max-width: 100vw;
overflow: hidden;
}
.glide {
max-width: 320px;
margin-left: auto;
margin-right: auto;
}
.glide__track {
overflow: visible!important;
}
const glide = new Glide('.glide', {
type: 'carousel',
breakpoints: {
1280: {
gap: 16,
focusAt: "center",
perView: 1,
peek: {
before: 16,
after: 16
},
},
}
}).mount({Swipe, Controls, Breakpoints });

ExtJs 4.2 - Cancelling/clearing the animations chain for a component

I'm building a web app and there's a part where if a button is clicked, this animation chain will execute:
var textReference = Ext.getCmp('splashText');
var checker = Ext.getCmp('arrow');
var img;
//for some reason, the logic is flipped
if(checker){
img = Ext.getCmp('arrow');
}
else{
console.log('checker is defined');
img = Ext.create('Ext.window.Window', {
header: false,
style: 'background-color: transparent; border-width: 0; padding: 0',
bodyStyle: 'background-color: transparent; background-image: url(graphics/arrow_1.png); background-size: 100% 100%;',
width: 70,
id: 'arrow',
height: 70,
border: false,
bodyBorder: false,
frame: false,
cls: 'noPanelBorder',
x: textReference.getBox().x - 90,
y: textReference.getBox().y - 10,
shadow: false,
});
}
img.show();
var origW = img.getBox().width,
origH = img.getBox().height,
origX = img.getBox().x,
origY = img.getBox().y;
//go down
Ext.create('Ext.fx.Anim', {
target: img,
duration: 500,
delay: 0,
from: {
x: textReference.getBox().x - 90,
y: textReference.getBox().y - 10,
},
to: {
y: origY + 180,
opacity: 1,
}
});
//bounce up 1st
Ext.create('Ext.fx.Anim', {
target: img,
duration: 500,
delay: 500,
from: {
},
to: {
y: origY + 50,
}
});
//fall down 1st
Ext.create('Ext.fx.Anim', {
target: img,
duration: 500,
delay: 1000,
from: {
},
to: {
y: origY + 180,
}
});
//bounce up 2nd
Ext.create('Ext.fx.Anim', {
target: img,
duration: 500,
delay: 1500,
from: {
},
to: {
y: origY + 100,
}
});
//fall down 2nd
Ext.create('Ext.fx.Anim', {
target: img,
duration: 500,
delay: 2000,
from: {
},
to: {
y: origY + 180,
}
});
//fade out
Ext.create('Ext.fx.Anim', {
target: img,
duration: 1000,
delay: 3500,
from: {
},
to: {
x: textReference.getBox().x - 90,
y: textReference.getBox().y - 10,
opacity: 0
}
});
It's just a basic animation where a "ball" will drop, then bounce up and down that makes it look like its bouncing up then down twice before staying at the bottom, then fades out.
It's working well, however, if the user clicks on the button over and over again while the previous animation chain is still animating, the animations will compound and the calculations for the positions will get compounded, making the ball appear much lower than it should.
To prevent this, what I want to happen is once the button gets clicked, the whole animation chain gets cancelled first, then the animation starts from the top. This is to ensure that any existing animation will get halted and then a fresh sequence will get started.
Does anyone have any idea on how to execute this? I've tried stopAnimation() but nothing happens.
The problem with ball dropping lower and lower is that you define original Y as textReference.getBox().y - 10 and then you try to move it to a different original Y + 180. Set your original Y first as textReference.getBox().y - 10 and then just use it for window placement, start of the aniamtion and other animation parts.
Secondly, you should use img.animate() instead of
Ext.create('Ext.fx.Anim', {
target: img,
If you do that, you can then use the stopAnimation() method you mentioned.
Example code:
var windowId = 'basketBallAnimation';
var img = Ext.getCmp( windowId );
// Set whatever you want here and use it
var originalX = 30;
var originalY = 30;
if( !img )
{
console.log('creating new image');
img = Ext.create('Ext.window.Window', {
header: false,
style: 'background-color: transparent; border-width: 0; padding: 0',
bodyStyle: 'background-color: transparent; background-image: url(//ph-live-02.slatic.net/p/6/molten-official-gr7-fiba-basketball-orange-4397-1336487-66ec7bf47676dee873cbb5e8131c4c1f-gallery.jpg); background-size: 100% 100%;',
width: 70,
height: 70,
id: windowId,
border: false,
bodyBorder: false,
frame: false,
cls: 'noPanelBorder',
x: originalX,
y: originalY,
shadow: false,
});
}
img.stopAnimation();
img.show();
// go down
img.animate({
duration: 500,
from: {
x: originalX,
y: originalY,
},
to: {
y: originalY + 180,
}
});
// ...
Working fiddle here.
Other off-topic comments on your coding style:
There's no need to save the image window to 'checker' and if the 'checker' exists to call Ext.getCmp() again, it saves time just to get the image and create it, if it is not saved.
Generally use variables more to store your data instead of calling the same method numerous times (textReference.getBox().x - 90 is called three times just in your small snippet. If you ever want to change it, you have to look really carefully where else it is applied).
If at all possible, avoid defining any style in ExtJS. Add cls configuration with CSS class and apply your styles in separate CSS file.

Categories