Linear Gradients not working with javascript - javascript

I have this, it worked before if I set the background and put the linear gradient inside the data-src, but when I changed it to this so that it would support more browsers, it isn't working anymore. The background gets set to an image but the gradient isn't showing up. The message that gets sent to the console is
linear-gradient(to top, rgba(2, 0, 36, .8) 0%, rgba(0, 0, 0, 0) 100%), url( '/static/images/mountain.jpg');
var url = "url( '" + slide.dataset.src + "')";
slide.style.backgroundImage = url;
if (slide.dataset.type == 'linear') {
var direction = slide.dataset.lindir;
var linstart = slide.dataset.linstart;
var linend = slide.dataset.linend;
var gradient = "linear-gradient(" + direction + ", " + linstart + ", " + linend + ")";
if (!(url == null)) {
gradient += (", " + url);
}
gradient += (";");
console.log(gradient);
slide.style.background = "-moz-" + gradient;
slide.style.background = "-webkit-" + gradient;
slide.style.background = gradient;
}
<div class="content category cursor-hand has-text-centered load" data-type="linear" data-lindir="to top" data-linstart="rgba(2, 0, 36, .8) 0%" data-linend="rgba(0, 0, 0, 0) 100%" data-src="{{ category.url }}">

The root problem is that you don't need the semicolon you are adding because you are setting the style in JavaScript, not adding a style to a stylesheet. I've commented that out below, and you can see that it works.
As others have pointed out, you are also doing your vendor prefixes incorrectly. See Setting vendor-prefixed CSS using javascript for more info on that topic.
Note, though, that support for multiple CSS backgrounds goes back to IE 9, so you probably don't need prefixes at all.
One thing to note is that since you are not setting any other background properties in your JS besides the background-image it would probably be best to use style.backgroundImage throughout instead of switching to style.background. This will let you control the other properties included in the background shorthand in your stylesheet.
var slide = document.querySelector('.slide');
var url = "url( '" + slide.dataset.src + "')";
slide.style.backgroundImage = url;
if (slide.dataset.type == 'linear') {
var direction = slide.dataset.lindir;
var linstart = slide.dataset.linstart;
var linend = slide.dataset.linend;
var gradient = "linear-gradient(" + direction + ", " + linstart + ", " + linend + ")";
if (!(url == null)) {
gradient += (", " + url);
}
//gradient += (";");
console.log(gradient);
slide.style.MozBackground = gradient;
slide.style.WebkitBackground = gradient;
slide.style.background = gradient;
}
.slide {
width: 300px;
height: 300px;
}
<div class="slide content category cursor-hand has-text-centered load" data-type="linear" data-lindir="to top" data-linstart="rgba(2, 0, 36, .8) 0%" data-linend="rgba(0, 0, 0, 0) 100%" data-src="{{ category.url }}"></div>

Related

Mobile Transform Origin Property not consistent with Web

I have an application I am developing that allows users to drop "Pins" on an SVG. These pins can be moved around the underlying SVG and the coordinates are saved in a database. The pins also have a "center of mass" of bottom center, I store the coordinates of the tip of the pin, not the 0,0 origin of the pin icon.
I am trying to implement a functionality, that will allow the pins to show larger when zoomed out of the underlying SVG, and scale smaller when zooming in (think google maps, if you look at a zoomed out map of all restaurants and then zoom in, the pins get smaller and more spread out).
I have this feature working on desktop web, see images below
However, on mobile, the same code causes the pins to exist in a different location, and when zooming I can see them scaling down to the top left point, and not the center bottom like the desktop client.
JS Code that is creating the scaling styles and logic:
if (instance) {
instance.dispose();
instance = panzoom($('#partialDiv')[0]);
var pins = Array.from(document.querySelectorAll('.draggable'));
instance.on('transform', function(pz) {
var transform = instance.getTransform();
pins.forEach(pin => {
if (transform.scale > 10 && transform.scale < 18) {
pin.setAttribute("transform", 'matrix(' +
15 / transform.scale + ', 0, 0, ' +
15 / transform.scale + ', ' +
pin.transform.baseVal[0].matrix.e + ', ' + pin.transform.baseVal[0].matrix.f + ')');
var pinStyle = pin.style;
pin.setAttribute("transform-origin", "" + pin.getBBox().width / 2 + " " + pin.getBBox().height + "0px");
pinStyle.transformBox = 'fill-box';
pin.style['-webkit-transform-origin-x'] = '50%';
pin.style['-webkit-transform-origin-y'] = 'bottom';
pinStyle.transformBox = 'fill-box';
} else if (transform.scale > 18) {
pin.setAttribute("transform", 'matrix(0.8, 0, 0, 0.8, ' +
pin.transform.baseVal[0].matrix.e + ', ' + pin.transform.baseVal[0].matrix.f + ')');
var pinStyle = pin.style;
pin.setAttribute("transform-origin", "" + pin.getBBox().width / 2 + " " + pin.getBBox().height + "0px");
pinStyle.transformBox = 'fill-box';
pin.style['-webkit-transform-origin-x'] = '50%';
pin.style['-webkit-transform-origin-y'] = 'bottom';
} else {
pin.setAttribute("transform", 'matrix(2, 0, 0, 2, ' +
pin.transform.baseVal[0].matrix.e + ', ' + pin.transform.baseVal[0].matrix.f + ')');
var pinStyle = pin.style;
pin.setAttribute("transform-origin", "" + pin.getBBox().width / 2 + " " + pin.getBBox().height + "0px");
pinStyle.transformBox = 'fill-box';
pin.style['-webkit-transform-origin-x'] = '50%';
pin.style['-webkit-transform-origin-y'] = 'bottom';
}
});
});
}
Why would the pins be displayed at a different origin on Chrome Desktop vs. Chrome IOS? Same is true for other desktop browsers and Safari on mobile. I have tried variations of webkit styles but it does not seem to change this behavior. Any advice is much appreciated.
After hours of troubleshooting I learned that there is a bug on IOS webkit 16.2+ that does not allow transform-origin to work with a transform attribute. Only the transform being performed in CSS will work with a transform-origin style.
Useful resource for anyone having an issue similar to me:
https://caniuse.com/mdn-svg_attributes_presentation_transform-origin

Altering background color to match video changes by browser

I would like the background of a video to match the background of its container. However, setting the container background manually has different results in different browsers (apparently due to localized hardware acceleration settings).
The solution is to read the color of the pixels in the video and update the background accordingly-- originally found here ---> https://stackoverflow.com/a/44523649/4072697
However, this method (including the one presented in the comment for it) produce the same result (different colors in different browsers)
This jsfiddle will not run the video due to cross origin errors, but includes the code:
HTML:
<div class="container">
<video class="videos" id="test" controls="none" autoplay="" loop name="media"><source src="https://r4---sn-ab5szne7.googlevideo.com/videoplayback?expire=1574210358&ei=1jbUXaubDo_t8gTuhJzwDw&ip=24.103.48.189&id=o-AMlyNgFeuPfxNCz0P6eVhp14foi9XPmWLqDxWO5zEwYA&itag=22&source=youtube&requiressl=yes&mm=31,26&mn=sn-ab5szne7,sn-vgqsknll&ms=au,onr&mv=m&mvi=3&pl=18&initcwndbps=1726250&mime=video/mp4&ratebypass=yes&dur=5.363&lmt=1471775895725173&mt=1574188655&fvip=4&fexp=23842630&c=WEB&sparams=expire,ei,ip,id,itag,source,requiressl,mime,ratebypass,dur,lmt&sig=ALgxI2wwRQIgJuAGaoYOYn6-XQ9ylB8uNwW2rKt09Q2zkixlP-5r4-ACIQCqMpK0BRTwnTzErcNFADAKc7k0YQPjBxJJAQD2vSRR7w==&lsparams=mm,mn,ms,mv,mvi,pl,initcwndbps&lsig=AHylml4wRgIhAOYG1-AAZcBkmaJJI502ztNGkv_9dUhOPNd8kZpJCYLRAiEA9BeuIqWpXG5JMtTFTgDCtmEsoaz0A7zOl6Lku3bj6bQ=" type="video/mp4"></video>
</div>
JS:
//allow crossOrigin
var testVid = document.getElementById('test')
testVid.crossOrigin = "Anonymous";
function drawingLoop() {
requestId = window.requestAnimationFrame(drawingLoop)
ctx.drawImage(vid, 0, 0, vidWidth, vidHeight, 0, 0, canvas.width, canvas.height);
}
function setVideoBgColor(vid, backgroundElement) {
var canvas = document.createElement("canvas");
//size of canvas space to copy pixel onto
canvas.width = 10;
canvas.height = 10;
var ctx = canvas.getContext("2d");
ctx.drawImage(vid, 0, 0, 10, 10);
var p = ctx.getImageData(0, 0, 10, 10).data;
var colorBoost = 0;
var colorR = p[0]+colorBoost;
var colorG = p[1]+colorBoost;
var colorB = p[1]+colorBoost;
//colorLayer.data[pixelPos];
backgroundElement.style.backgroundColor = "rgb(" + colorR+ "," + colorG + "," + colorB + ")";
}
document.getElementById('test').addEventListener("play",function(){
setVideoBgColor(document.getElementById('test'),this.parentElement);
})
CSS:
.container{
background-color: yellow;
width: 100vw;
height: 100vh;
}
#test{
margin-top:20%;
margin-left:15%;
width:70%;
height:auto;
}

Radial cursor with Background Image using JavaScript

I'm trying to create a radial cursor on a site with a background image.
I currently have two problems:
It currently works with Chrome, but not with Firefox. I receive a parsing error for "background" when it occurs.
On Chrome, sometimes two cursors appear instead of 1 and it appears to be mirrored, which can be seen in this JSFiddle
I'm currently using the following code adopted from here.
How would I go about fixing this? Thanks!
.
CSS:
html {
background: url("blocpartylandscape.jpg") no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
Javascript:
$(function() {
var originalBGplaypen = $("html").css("background"),
x, y, xy, bgWebKit, bgMoz,
lightColor = "rgba(255,255,255,0.75)",
gradientSize = 100;
var originalBG = $('html').css("background");
$('html')
.mousemove(function(e) {
x = e.pageX - this.offsetLeft;
y = e.pageY - this.offsetTop;
xy = x + " " + y;
bgWebKit = "-webkit-gradient(radial, " + xy + ", 0, " + xy + ", 100, from(rgba(255,255,255,0.8)), to(rgba(255,255,255,0.0))), " + originalBG;
bgMoz = "-moz-radial-gradient(" + x + "px " + y + "px 45deg, circle, " + lightColor + " 0%, " + originalBG + " " + gradientSize + "px)";
$(this)
.css({ background: bgWebKit })
.css({ background: bgMoz });
}).mouseleave(function() {
$(this).css({ background: originalBG });
});
});
To make things simpler for Firefox, I added another HTML element. The element is a container around everything in body. I did this so that the html element can have its persistent background image and not be disturbed by the competing radial cursor background (which is also an image). Chrome was okay with sharing the html element for both the background image and the radial cursor, but Firefox was not.
<div class="container">
<h1>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi egestas in diam vitae elementum. </h1>
</div>
I'm using the newly added container as a canvas on which to display the radial cursor.
.container {
height: 100vh;
}
Now, in your JavaScript, I simply use that new container element to show the radial background.
$(".container")
.css({ background: bgWebKit })
.css({ background: bgMoz });
And then for removing the radial cursor.
.mouseleave(function() {
$(".container").css({ background: originalBG });
});
Firefox also needs an rgb or rgba value instead of whatever your call to background was returning. That value wasn't a valid argument to the radial background, though the following is valid:
bgMoz = "-moz-radial-gradient(" + x + "px " + y + "px 45deg, circle, " + lightColor + " 0%, rgba(255,255,255,0.0) " + gradientSize + "px)";
You may want to refactor a bit more. My main goal was to get things working for you. Below is a demo which works in both Chrome and Firefox.
https://jsfiddle.net/7d17ufm7/

javascript code to change clip rect settings

What I'm trying to accomplish is when the window is resized, the blurred image is resized as well. For some reason the code is not working. Can someone spot what is wrong and what I need to do to correct the code. Thanks.
CSS -
/* ------- BLUR BEHIND MESSAGE HOLDER CONTAINER SETTINGS ------- */
img.clipphoto {
/*--- CLIP SETTINGS: top, right, bottom, left ---*/
clip: rect(18px,770px,600px,240px);
position: absolute;
-webkit-filter: blur(10px);
-moz-filter: blur(10px);
-o-filter: blur(10px);
-ms-filter: blur(10px);
filter: blur(10px);
}
JS -
window.addEventListener('resize', function(event){
var vInnerHeight= window.innerHeight;
var t = "18";
var r = "770";
var b = vInnerHeight-140;
var l = "240";
var clipString = "rect(" + t + "px " + r + "px " + b + "px " + l + "px)";
document.getElementByClassName(clipphoto).style.clip = clipString;
HTML -
<!-- blurred photo of pix -->
<img src="images/image1.png" width="1200" height="620" alt="" class="clipphoto">
There is no getElementByClassName() function. It's getElementsByClassName() (plural).
And you want the string "clipphoto", not the (non-existant) variable named clipphoto:
var clipString = "rect(" + t + "px, " + r + "px, " + b + "px, " + l + "px)";
document.getElementsByClassName('clipphoto')[0].style.clip = clipString;
Believe the values should be comma separated, not space separated
var clipString = "rect(" + t + "px," + r + "px," + b + "px," + l + "px)";
document.getElementsByClassName('clipphoto')[0].style.clip = clipString;
Edit: incorporated class accessor errror by Paul Roub too

Does there exist a method or plugin to allow for rotate transforms to respect div boundries?

By default, the css rotate property seems to occur after tag spacing. For instance, if you have two divs in a column and you rotate one, they overlap. It's possible I completely missed some aspect of css or html that handles this issue, have I?
The obvious solution seems to be to write some javascript to manage the placement of elements post rotate. Does a plugin exist that helps handle this spacing? The only thing close I could locate was the jquery-rotate plug, but it does not seems to provide any functionality with regard to spacing.
Relevant html/css demonstrating the spacing problem.
HTML
<div class="red-box rotate-right"></div>
<div class="blue-box"></div>​
CSS
.rotate-right {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.red-box{
height: 50px;
width: 100px;
background: red;
}
.blue-box{
height: 50px;
width: 100px;
background: blue;
}
Alright, beware this is ugly to look at.
First, I used code from CSS-Tricks to get the angle of rotation. Then, I use some algebra to find the distance (from the center of the rotated element) to the sides of a box that contains the element. Then I add margins to the edge of the rotated element to create (or remove) extra space where needed. This also takes into account the original margins (if any).
Usage:
After rotating an element, call $(rotatedElement).space([grow],[shrink]). See code comments for argument descriptions.
jQuery.fn.space = function(grow,shrink){
// grow = Grow area around element to fit? (true/false)
// shrink = Shrink area around element to fit? (true/false)
var el = this.get(0);
if(typeof(grow)=='undefined'){
grow = true; // Default to grow extra space when needed
}
if(typeof(shrink)=='undefined'){
shrink = false; // Default to not shrink at all
}
//Get angle of rotated element
var st = window.getComputedStyle(el, null);
var tr = st.getPropertyValue("-webkit-transform") ||
st.getPropertyValue("-moz-transform") ||
st.getPropertyValue("-ms-transform") ||
st.getPropertyValue("-o-transform") ||
st.getPropertyValue("transform");
var v = tr.split('(')[1].split(')')[0].split(',');
var scale = Math.sqrt(v[0]*v[0] + v[1]*v[1]);
var angle = Math.round(Math.atan2(v[1], v[0]) * (180/Math.PI));
//Save or recall original margins
var m = new Array();
if(el.getAttribute('margins')==null){
m[0] = st.getPropertyValue("margin-left").match(/\d+/);
m[1] = st.getPropertyValue("margin-right").match(/\d+/);
m[2] = st.getPropertyValue("margin-top").match(/\d+/);
m[3] = st.getPropertyValue("margin-bottom").match(/\d+/);
el.setAttribute('margins',m[0]+","+m[1]+","+m[2]+","+m[3]);
} else {
m = el.getAttribute('margins').split(',');
console.log(m);
}
//Get center coords
var cx = st.getPropertyValue("width").match(/\d+/)/2;
var cy = st.getPropertyValue("height").match(/\d+/)/2;
//Convert radian values to degrees
function toDeg(angle){
return angle*Math.PI/180;
}
// Coords of the corners
// (starting from top-left and proceeding clockwise)
// relative to the center of the element
// c[cornerID][x|y]
var c = [ [Math.round(cx*Math.cos(toDeg(angle-180))
+ cy*Math.cos(toDeg(angle-90))),
Math.round(cx*Math.sin(toDeg(angle-180))
+ cy*Math.sin(toDeg(angle-90)))],
[Math.round(cx*Math.cos(toDeg(angle))
+ cy*Math.cos(toDeg(angle-90))),
Math.round(cx*Math.sin(toDeg(angle))
+ cy*Math.sin(toDeg(angle-90)))],
[Math.round(cx*Math.cos(toDeg(angle))
+ cy*Math.cos(toDeg(angle+90))),
Math.round(cx*Math.sin(toDeg(angle))
+ cy*Math.sin(toDeg(angle+90)))],
[Math.round(cx*Math.cos(toDeg(angle-180))
+ cy*Math.cos(toDeg(angle+90))),
Math.round(cx*Math.sin(toDeg(angle-180))
+ cy*Math.sin(toDeg(angle+90)))]
];
var elx = ([c[0][0], c[1][0], c[2][0], c[3][0]]).sort(function(a,b){
return(a*1)-(b*1);});
var ely = ([c[0][1], c[1][1], c[2][1], c[3][1]]).sort(function(a,b){
return(a*1)-(b*1);});
var b = [-elx[0], elx[3], -ely[0], ely[3]]; // [Left, Right, Top, Bottom]
if(grow){
if(b[0]-cx>0) el.style.marginLeft = (m[0] + b[0]-cx) + "px";
if(b[1]-cx>0) el.style.marginRight = (m[1] + b[1]-cx) + "px";
/*}
if(growY){ */
if(b[2]-cy>0) el.style.marginTop = (m[2] + b[2]-cy) + "px";
if(b[3]-cy>0) el.style.marginBottom = (m[3] + b[3]-cy) + "px";
}
if(shrink){
if(b[0]-cx<0) el.style.marginLeft = (m[0] + b[0]-cx) + "px";
if(b[1]-cx<0) el.style.marginRight = (m[1] + b[1]-cx) + "px";
/*}
if(shrinkY){ */
if(b[2]-cy<0) el.style.marginTop = (m[2] + b[2]-cy) + "px";
if(b[3]-cy<0) el.style.marginBottom = (m[3] + b[3]-cy) + "px";
}
}
You may wish to split (grow and shrink) into (growX, growY and shrinkX, shrinkY) depending on what's going on in your live site, so you don't break your layout. To do so, just adjust/add the arguments and defaults at the top, and the if(grow)/if(shrink) statements at the bottom.

Categories

Resources