I got an example code from codepen and I wanted to understand it better. I noticed that the js code is compiled with Babel. Since I'm quite new to JS I would be more comfortable to look at a standard javascript code, so I wanted to ask you if there's some way to convert a babel js into a regular js. I did some research but I couldn't find anything
By the way, this is the Babel code
const parent = document.getElementById("projects");
const closeButton = document.getElementById("project-close");
const projectItems = document.querySelectorAll(".project-item");
closeButton.addEventListener("click", onProjectClose);
projectItems.forEach(item => item.addEventListener("click", onProjectClick));
function onProjectClick(event) {
const { target } = event;
const { width, height, top, left } = target.getBoundingClientRect();
const clone = document.createElement("div");
clone.style.height = height + "px";
clone.style.width = width + "px";
clone.style.top = top + "px";
clone.style.left = left + "px";
clone.style.position = "absolute";
clone.style.zIndex = 10;
clone.classList.add("project-item");
clone.classList.add("clone");
clone.innerHTML = target.innerHTML;
document.body.appendChild(clone);
gsap.timeline().
to(clone, 1.5, {
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100vh",
ease: Expo.easeInOut }).
add(() => document.body.classList.add("project-page")).
set(clone, {
overflow: "auto" });
}
function onProjectClose() {
document.body.classList.remove("project-page");
const clone = document.querySelector(".clone");
gsap.to(clone, 1, {
clipPath: "inset(100% 0 100% 0)",
ease: Sine.easeInOut,
onComplete() {
clone.remove();
} });
gsap.to(clone.querySelector("img"), 1, {
scale: 0.7,
ease: Sine.easeInOut });
}
Related
the goal is to replace native Google Charts labels with icons. Doing:
google.visualization.events.addListener(chart, 'ready', function () {
const chartLayout = chart.getChartLayoutInterface(),
chartBounds = chartLayout.getChartAreaBoundingBox();
for (let i = 0; i < chartData.getNumberOfRows(); i++) {
console.log(chartLayout)
const axisLabelBounds = chartLayout.getBoundingBox(`vAxis#0#label#${i}`),
thumb = container.appendChild(document.createElement('img'));
console.log(axisLabelBounds)
thumb.src = chartData.getProperty(i, 0, 'icon');
thumb.style.position = 'absolute';
thumb.style.width = '16px';
thumb.style.height = '16px';
thumb.style.zIndex = '1';
thumb.style.top = axisLabelBounds.top - 8 + 'px';
thumb.style.left = axisLabelBounds.left - 25 + 'px';
}
});
chart.draw(chartData, getBarChartOptions({
title: null
}))
It works great on macOS and Linux:
{left: 36.75, top: 111.890625, width: 0.25, height: 277.21875}
But not on Windows:
{left: 0, top: 0, width: 0, height: 0}
Same browser, the latest Chrome. Any ideas?
Thanks a lot!
On Saabi's github for vminpoly, a vw and vh unit polyfill (https://github.com/saabi/vminpoly), it says:
Only linked stylesheets are being parsed right now but it's very easy
to also parse 'style' elements.
How would vw and vh CSS inside style elements work with vminpoly?
You could refer to the code below to support vh, vw in particular:
(function($, window) {
var $win = $(window),
_css = $.fn.css;
function viewportToPixel(val) {
var percent = val.match(/\d+/)[0] / 100,
unit = val.match(/[vwh]+/)[0];
return (unit == 'vh' ? $win.height() : $win.width()) * percent + 'px';
}
function parseProps(props) {
var p, prop;
for (p in props) {
prop = props[p];
if (/[vwh]$/.test(prop)) {
props[p] = viewportToPixel(prop);
}
}
return props;
}
$.fn.css = function(props) {
var self = this,
update = function() {
return _css.call(self, parseProps($.extend({}, props)));
};
$win.resize(update);
return update();
};
}(jQuery, window));
//Usage:
$('div').css({
height: '50vh',
width: '50vw',
marginTop: '25vh',
marginLeft: '25vw',
fontSize: '10vw'
});
body {
margin: 0;
}
div {
background: #fa7098;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>hello</div>
The result in IE is like this:
So I've created a smooth scroll effect on my website, works nice, but I'm having an issue with Scrollmagic. When scrolling down, I'm translating elements, but it stutters. A lot. When I disable my smooth scroll script, everything works fine again.
BTW : I'm using Webpack and GSAP for the animations.
My guess is Scrollmagic isn't aware of the animation so it's using the end value, not the current one. But I can't find out how to fix this
Here is my smooth scroll :
import { TweenLite } from 'gsap';
const html = document.documentElement;
const body = document.body;
const scroller = {
target: document.querySelector('.scroll-container'),
ease: 0.1, // <= scroll speed
endY: 0,
y: 0,
resizeRequest: 1,
scrollRequest: 0,
};
let requestId = null;
TweenLite.set(scroller.target, {
rotation: 0.01,
force3D: true,
});
window.addEventListener('load', onLoad);
function onLoad() {
updateScroller();
window.focus();
window.addEventListener('resize', onResize);
document.addEventListener('scroll', onScroll);
}
function updateScroller() {
const resized = scroller.resizeRequest > 0;
if (resized) {
const height = scroller.target.clientHeight;
body.style.height = `${height}px`;
scroller.resizeRequest = 0;
}
const scrollY = window.pageYOffset || html.scrollTop || body.scrollTop || 0;
scroller.endY = scrollY;
scroller.y += (scrollY - scroller.y) * scroller.ease;
if (Math.abs(scrollY - scroller.y) < 0.05 || resized) {
scroller.y = scrollY;
scroller.scrollRequest = 0;
}
TweenLite.set(scroller.target, {
y: -scroller.y,
});
requestId = scroller.scrollRequest > 0 ? requestAnimationFrame(updateScroller) : null;
}
function onScroll() {
scroller.scrollRequest += 1;
if (!requestId) {
requestId = requestAnimationFrame(updateScroller);
}
}
function onResize() {
scroller.resizeRequest += 1;
if (!requestId) {
requestId = requestAnimationFrame(updateScroller);
}
}
And the Scrollmagic part :
import $ from 'jquery';
import * as ScrollMagic from 'scrollmagic';
import { TweenMax, TimelineMax, Power0 } from 'gsap';
import { ScrollMagicPluginGsap } from 'scrollmagic-plugin-gsap';
ScrollMagicPluginGsap(ScrollMagic, TweenMax, TimelineMax);
const controller = new ScrollMagic.Controller();
$('.big-outline-text').each(function() {
const tl = new TimelineMax();
const child = $(this);
if ($(this).hasClass('right-to-left')) {
tl.to(child, 2, { x: -300, ease: Power0.easeInOut });
} else if ($(this).hasClass('left-to-right')) {
tl.fromTo(child, 2, { x: -300 }, { x: 0, ease: Power0.easeInOut }, '+=1');
}
const scene = new ScrollMagic.Scene({
triggerElement: this,
triggerHook: 0.9,
duration: '110%',
})
.setTween(tl)
.addTo(controller);
});
$('.bottom-to-top').each(function() {
const tl2 = new TimelineMax();
const child = $(this);
if ($(this).hasClass('bottom-to-top')) {
tl2.fromTo(child, 2, { y: -300 }, { y: 100, ease: Power0.easeInOut });
}
const scene = new ScrollMagic.Scene({
triggerElement: this,
triggerHook: 0.9,
duration: '220%',
})
.setTween(tl2)
.addTo(controller);
});
I'm sure i'm not the first one having this problem, but i couldn't find any answer.
I managed to solve my issue with a refresh function for the scrollbar. Like in this codepen https://codepen.io/emraher/pen/GPRJEZ?editors=1010
They set the scrollbar and the scrollmagic scene as vars, and then this little gem
var elem = document.querySelector(".content");
var scrollbar = Scrollbar.init(elem)
scrollbar.addListener(() => {
scene.refresh()
})
I have problems displaying recently uploaded photos to a form. If the image was made by phone, it may have an exif property, but the browser does not handle this property, it turns out that the picture can be flipped over or on the side.
upside down picture
I solved this problem with the exif-js library. Having written (having stolen on some website) a component and having spent a lot of time, I achieved that during loading and processing, the picture turns in the right direction.
right side picture
But during the test, we found out that on iPhones, if you download not from photos, but take photos vertically manually, then the picture generally goes beyond the div to the lower left corner.
iphone incorrectly image
After that all other photos are also displayed incorrectly. On android device all is fine.
In this img-tag: src changes dynamicly and I need 'transform' dynamicly too, so I need to use updated() method. I know this is bad code, but...
Usage:
<div class="form-group">
<div class="row">
<div class="col-md-6 edit-activity-images">
<auto-rotate><img class="edit-activity-images-inner" alt="activity"
:src="getUploadedImageBackground()||staticFile('images/img-place-holder.png')"
></auto-rotate>
Style
edit-activity-images-inner{
object-fit: cover;
width: 100%;
height: 100%;
}
Component
<template>
<div class="holder">
<slot></slot>
</div>
</template>
<script>
import imagesLoaded from 'imagesloaded'
import EXIF from 'exif-js'
const rotateAngles = [
{},
{y: 0, z: 0},
{y: 180, z: 0},
{y: 0, z: 180},
{y: 180, z: 180},
{y: 180, z: -90},
{y: 0, z: -90},
{y: 180, z: 90},
{y: 0, z: 90}
];
function getOrientation(el) {
return new Promise(function (resolve) {
imagesLoaded(el, function () {
EXIF.getData(el, function () {
const orientation = EXIF.getTag(this, 'Orientation');
resolve(orientation);
})
})
})
}
function getRotationAngle(newOrientation, oldOrientation) {
const y = rotateAngles[newOrientation].y - rotateAngles[oldOrientation].y;
let z = rotateAngles[newOrientation].z - rotateAngles[oldOrientation].z;
if (y)
z = z * -1;
return { y, z }
}
const recently_added = {};
const havent_exif = {};
export default {
name: "AutoRotate",
updated() {
const slot = this.$slots.default[0];
if (slot.tag !== 'img') {
console.error('Warning: slot should be an img tag.');
return;
}
const holder = this.$el;
const img = holder.childNodes[0];
img.exifdata = undefined;
if (recently_added[img.src]) {
img.style['transform'] = recently_added[img.src];
return
} else if (havent_exif[img.src]) {
img.style['transform'] = "translate(0px, 0px) rotateY(0deg) rotateZ(0deg)";
return;
}
getOrientation(img).then(function (currentOrientation) {
if (currentOrientation !== undefined) {
const angle = getRotationAngle(1, currentOrientation);
const transform = `rotateY(${angle.y}deg) rotateZ(${angle.z}deg)`;
let translate = '';
if (angle.z % 180 !== 0) {
const height = img.clientHeight;
const width = img.clientWidth;
translate = `translate(${(height - width) / 2}px, ${(width - height) / 2}px)`;
holder.style['width'] = `${height}px`;
holder.style['height'] = `${width}px`;
}
img.style['vertical-align'] = 'bottom';
img.style['transform'] = translate + ' ' + transform;
recently_added[img.src] = translate + ' ' + transform;
} else {
havent_exif[img.src] = true;
if (!recently_added[img.src]) {
img.style['transform'] = "translate(0px, 0px) rotateY(0deg) rotateZ(0deg)";
}
}
})
}
}
<style scoped>
.holder {
object-fit: cover;
width: 100%;
height: 100%;
}
</style>
Well, hope someone can help me and write what can I do...
Well, I removed this part of code, because it works incorrect. And it's done...
if (angle.z % 180 !== 0) {
const height = img.clientHeight;
const width = img.clientWidth;
translate = `translate(${(height - width) / 2}px, ${(width - height) / 2}px)`;
holder.style['width'] = `${height}px`;
holder.style['height'] = `${width}px`;
}
I'm working on my own canvas drawer project, and just stuck in the zoom in/out function. In my project I'm using scale and translate to make the zoom, as I want to keep all the canvas and its elements in the center.
After sketching a little bit(not a math genius), I succeeded to draw out the following formula to use in the translate process, so the canvas will be kept in the middle of its view port after zooming: Old width and height / 2 - New width and height(which are old width and height multiply by scale step, which is 1.1 in my case) / 2.
Logically speaking, that should make it work. But after trying few times the zoom in and zoom out, I can clearly see that the canvas has a little offset and it's not being centered to the middle of the viewport(by viewport I mean the stroked square representing the canvas).
I took my code out of my project and put it in fiddle, right here:
https://jsfiddle.net/s82qambx/3/
index.html
<div id="letse-canvas-container">
<canvas id="letse-canvas" width="300px" height="300px"></canvas>
<canvas id="letse-upper-canvas" width="300px" height="300px"></canvas>
</div>
<div id="buttons">
<button id="zoomin">
Zoom-in
</button>
<button id="zoomout">
Zoom-out
</button>
</div>
main.js
const canvas = {
canvas: document.getElementById('letse-canvas'),
upperCanvas: document.getElementById('letse-upper-canvas')
};
canvas.canvas.ctx = canvas.canvas.getContext('2d');
canvas.upperCanvas.ctx = canvas.upperCanvas.getContext('2d');
const CANVAS_STATE = {
canvas: {
zoom: 1,
width: 300,
height: 300
}
}
const Elements = [
{
x: 20,
y: 20,
width: 30,
height: 40
},
{
x:170,
y:30,
width: 100,
height: 100
}
];
const button = {
zoomin: document.getElementById('zoomin'),
zoomout: document.getElementById('zoomout')
}
button.zoomin.addEventListener('click', (e) => {
canvasZoomIn(e, canvas);
});
button.zoomout.addEventListener('click', (e) => {
canvasZoomOut(e, canvas);
});
function canvasZoomIn(e, canvas) {
const zoomData = getZoomData('in');
canvas.upperCanvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.upperCanvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.upperCanvas.ctx.clearRect(0, 0, 300, 300);
canvas.canvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.canvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.canvas.ctx.clearRect(0, 0, 300, 300);
Elements.forEach((element) => {
canvas.canvas.ctx.strokeRect(element.x, element.y, element.width, element.height);
});
CANVAS_STATE.canvas.zoom = zoomData.scale;
CANVAS_STATE.canvas.width = zoomData.docWidth;
CANVAS_STATE.canvas.height = zoomData.docHeight;
console.log(CANVAS_STATE.canvas.zoom, 'zoom');
console.log(CANVAS_STATE.canvas.width, 'width');
console.log(CANVAS_STATE.canvas.height, 'height');
canvas.canvas.ctx.strokeRect(0, 0, 300, 300);
canvas.canvas.ctx.beginPath();
canvas.canvas.ctx.moveTo(0, 150);
canvas.canvas.ctx.lineTo(300, 150);
canvas.canvas.ctx.stroke();
CANVAS_STATE.canvas.draggable = canvas.canvas.width < CANVAS_STATE.canvas.width || canvas.canvas.height < CANVAS_STATE.canvas.height;
}
function canvasZoomOut(e, canvas) {
const zoomData = getZoomData('out');
canvas.upperCanvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.upperCanvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.upperCanvas.ctx.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
canvas.canvas.ctx.scale(zoomData.zoomStep, zoomData.zoomStep);
canvas.canvas.ctx.translate(zoomData.translateX, zoomData.translateY);
canvas.canvas.ctx.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
Elements.forEach((element) => {
canvas.canvas.ctx.strokeRect(element.x, element.y, element.width, element.height);
});
CANVAS_STATE.canvas.zoom = zoomData.scale;
CANVAS_STATE.canvas.width = zoomData.docWidth;
CANVAS_STATE.canvas.height = zoomData.docHeight;
console.log(CANVAS_STATE.canvas.zoom, 'zoom');
console.log(CANVAS_STATE.canvas.width, 'width');
console.log(CANVAS_STATE.canvas.height, 'height');
canvas.canvas.ctx.strokeRect(0, 0, 300, 300);
canvas.canvas.ctx.beginPath();
canvas.canvas.ctx.moveTo(0, 150);
canvas.canvas.ctx.lineTo(300, 150);
canvas.canvas.ctx.stroke();
CANVAS_STATE.canvas.draggable = canvas.canvas.width < CANVAS_STATE.canvas.width || canvas.canvas.height < CANVAS_STATE.canvas.height;
}
function getZoomData(zoom) {
const zoomStep = zoom === 'in' ? 1.1 : 1 / 1.1;
const scale = CANVAS_STATE.canvas.zoom * zoomStep;
const docWidth = CANVAS_STATE.canvas.width * zoomStep;
const docHeight = CANVAS_STATE.canvas.height * zoomStep;
const translateX = CANVAS_STATE.canvas.width / 2 - docWidth / 2;
const translateY = CANVAS_STATE.canvas.height / 2 - docHeight / 2;
console.log(zoomStep);
console.log(scale, 'check');
console.log(docWidth);
console.log(docHeight);
console.log(translateX, 'check');
console.log(translateY, 'check');
return {
zoomStep,
scale,
docWidth,
docHeight,
translateX,
translateY
};
}
main.css
#letse-canvas-container {
position: relative;
float: left;
}
#letse-canvas {
border: 1px solid rgb(0, 0, 0);
/* visibility: hidden; */
}
#letse-upper-canvas {
/* position: absolute; */
/* top: 0px; */
left: 0px;
border: 1px solid;
/* visibility: hidden; */
}
Can someone suggest a reason? What am I missing here?
OK! So I managed to derive the right formula after searching in the net and testing few options. I used:
function getZoomData(zoom) {
const zoomStep = zoom === 'in' ? 1.1 : 1 / 1.1;
const oldZoom = CANVAS_STATE.canvas.zoom;
const newZoom = oldZoom * zoomStep;
const zoomDifference = newZoom - oldZoom;
const docWidth = CANVAS_STATE.canvas.width * newZoom;
const docHeight = CANVAS_STATE.canvas.height * newZoom;
const translateX = (-(canvas.canvas.width / 2 * zoomDifference / newZoom));
const translateY = (-(canvas.canvas.height / 2 * zoomDifference / newZoom));