If I apply a .style.webkitTransform = 'translateX(10px)'; on an element and then I would like to add another .style.webkitTransform = 'translateX(10px)'; to reach a total of 20px is impossible.
The element will again be 10px.
How can I go around this?
(Except keeping the previous values and adding it to translateX like = preValue+current+'px';)
You've already figured out out the answer.
var pixels = parseFloat(element.style.webkitTransform.split(/[()]/)[1]);
pixels += 10;
element.style.webkitTransform = 'translateX(' + pixels + 'px)';
Related
I'm working with SVGs currently and came to a dead end.
The SVG has lines, which should scale together with zooming (so that they stay in balance: 100% width 10px --> 10% width 1px for example)
i scale all stroke-widths with this code:
var svgPath = this._svgContainer.find('svg [class*="style"]');
for (var i = 0; i < svgPath.length; ++i) {
var newStrokeWidth = this._oldStrokeWidth[i] * (1 / (width / imgData.w));
$(svgPath[i]).css(
'stroke-width', newStrokeWidth
);
}
Where width is the new width after zoom and imgData.w is the original unscaled width.
The problem with this is, if i zoom in to far. The stroke with becomes to small and leads to sub-pixel rendering. And supposedly black lines get grey-ish.
My Idea was to clip the value at a certain point to prevent it.
But as far as I know, I have to consider the Device Pixel ratio too, because of different screens (desktop, mobile, 4K)
Would be nice If someone can help me with an idea to fix my problem
We finally found a solution for this, in case anyone has the same problems:
1) Because of the panning of this._$svgElement and the calculation of vpx in a completely different section of the code the element is 'between' pixels. ( 100.88945px for x for example). This causes lines to blur.
I fixed this part with a simple Math.round().
this._hammerCanvas.on('panmove', (event: any) => {
const translate3d = 'translate3d(' + Math.round(this._oldDeltaX + ((vpx === imgData.x) ? 0 : vpx) + event.deltaX) + 'px, ' + Math.round(this._oldDeltaY + ((vpy === imgData.y) ? 0 : vpy) + event.deltaY) + 'px, 0)';
this._$svgElement.css({
transform: translate3d
});
}
2) To fix the problem between the SVG viewport and the line strength, I had to implement a method to calculate the strokewidth equal to 1 'real' pixel regarding the svgs dimension.
the updated code looks like this: (This is the inital code, after the SVG was loaded from the server. Inside the zooming, the old code from above is still the same)
const pixelRatio = devicePixelRatio || 1;
const widthRatio = this._initSVGWidth / svgContainerWidth;
const heightRatio = this._initSVGHeight / svgContainerHeight;
this._svgZoomFactor = Math.max(widthRatio, heightRatio);
const strokeWidth1px = this.computeStrokeWidth1px(widthRatio, heightRatio);
for (let i = 0; i < svgPaths.length; ++i) {
this._initalStrokeWidth[i] = parseFloat($(svgPaths[i]).css('stroke-width'));
const newStrokeWidth = Math.max(strokeWidth1px / pixelRatio, this._svgZoomFactor * this._initalStrokeWidth[i]);
$(svgPaths[i])[0].setAttribute('style', 'stroke-width:' + newStrokeWidth);
this._oldStrokeWidth[i] = newStrokeWidth;
}
and the compute:
protected computeStrokeWidth1px (widthRatio: number, heightRatio: number): number {
const viewBox = this._$svgElement[0].getAttribute('viewBox').split(' ');
const viewBoxWidthRatio = parseFloat(viewBox[2]) / this._$svgElement.width();
const viewBoxHeightRatio = parseFloat(viewBox[3]) / this._$svgElement.height();
return widthRatio > heightRatio ? viewBoxWidthRatio : viewBoxHeightRatio;
}
var newStrokeWidth = this._oldStrokeWidth[i] * (1 / (width / imgData.w));
newStrokeWidth = (newStrokeWidth < 1) ? 1 : newStrokeWidth;
newStrokeWidth will always be 1 or greater
I'm trying to make one-page scrolling but I have a small problem. I have
var main = document.getElementById('main');
window.addEventListener('scroll', function(){
window.scrollTo(0, 0);
var top = -main.offsetTop;
main.style.top = -100 + '%';
});
Now this only works once obviously, so I'm trying to put an addition operator so it deducts a 100% every time you scroll.
main.style.top -= 100 + '%';
but that doesn't work for some reason..
Addition works if I do this instead...
var top = main.offsetTop;
main.style.top = top - 100 + '%';
but this fucks things up since top is technically in px not %. So any ideas how to make main.style.top -= 100 + '%'; work or a good alternative instead?
Let me write the expression main.style.top -= 100 + '%'; in another way that means the same thing:
main.style.top -= (100 + '%' /* this is a string now */)
What happens if you -= a string from anything? The first expression that you put (main.style.top = top - 100 + '%';) was closer to what you want but still not right. If you want to subtract 100% of the top value every time, like you said you need to do it in terms of pixels, not percent. So first you need to find how many pixels is 100 percent, which looking at your code might just be the value of main.offsetTop for you. Then you need to subtract that value from the top value. So what you have first is close but I think you need:
var main = document.getElementById('main');
window.addEventListener('scroll', function(){
window.scrollTo(0, 0);
var top = main.offsetTop;
main.style.top -= top;
});
I need help showing/hiding text on a button click (specifically an arrow). I have a block of text that I have hidden and I need to slide it down in a time consistent with the arrow rotating 180 degrees. I also want it to do this only for the post above the arrow that was clicked. The solution I have come up with in this fiddle has many problems.
Here is the code:
$(function () {
var angle = -180,
height = "100%";
$(".down-arrow").click(function () {
$(".down-arrow").css({
'-webkit-transform': 'rotate(' + angle + 'deg)',
'-moz-transform': 'rotate(' + angle + 'deg)',
'-o-transform': 'rotate(' + angle + 'deg)',
'-ms-transform': 'rotate(' + angle + 'deg)',
});
$(".blog-post").animate({
'height' : height
});
angle -= 180;
height = "50px";
});
});
And these are the issues I am having:
It slides down way too fast
Once it slides back up it won't slide down again.
It does it for every post
This would be more dynamic and clean to use:
First we will take height's of all the .blog-post div's in an array.
Now making height: 50px of the div, after once we know actual height of all the div's. Which will helpful in making div smooth slide as we know height's.
Next on click of arrow class, we will toggle class which holds transform:rotate properties. Along with that we would check corresponding .blog-post div's height. So if it is more than 50px we would make it 50px, else we would take it's actual height from array and give to it.
Here is the JS/JQuery Code:
var totalNum = $('.blog-post').length; // Counting number of .blog-post div on page.
var i, myArray = [];
for (i = 0; i < totalNum; i++) {
var curHeight = $('.blog-post:eq(' + i + ')').outerHeight();
myArray.push(curHeight);
}
$('.blog-post').css('height', '50px');
$('.down-arrow').click(function () {
$(this).toggleClass('invert');
var index = $('.down-arrow').index(this);
var heightCheck = $('.blog-post:eq(' + index + ')').outerHeight();
if (heightCheck < 51) {
$('.blog-post:eq(' + index + ')').css('height', myArray[index] + 'px');
} else {
$('.blog-post:eq(' + index + ')').css('height', '50px');
}
});
Working : Fiddle
If you still do not understand feel free to ask.
I guess you should convert the 100% to pixels (with $(this).parent().innerHeight() or something like that, then it works well.
You should build some sort of toggle: keep track of which blog-post/arrow is up and which one is down (flag the blog posts or the arrows with some sort of class) and based on that, you should let it slide up or down.
Of course, you're referring to the post with a css selector. You should use a combination of $(this), .next() and .prev() functions in order to get the right post(s).
"It slides down way too fast"
Just set an animation duration. See the jquery.animate() documentation.
It seems that jquery is pretty buggy when it comes to animating using percentages. http://bugs.jquery.com/ticket/10669 http://bugs.jquery.com/ticket/9505 Try using pixels instead of percentage http://jsfiddle.net/8obybt1d/1/
"Once it slides back up it won't slide down again."
Because you are not changing the value of height back to hundred%
A rough piece of code:
if (height == "50px") {
height = "100%";
}
else {
height == "50px"
}
"It does it for every post"
Try using the 'this' keyword.
To solve point 2:
$(".blog-post").animate({
...
height = (height === "50px") ? height = "100%": height = "50px";
});
I am trying to add to the width of the element everytime the setInterval function is invoked
function setProgress(){
var bar = document.getElementById('progress-bar');
var width = 20;
bar.style.width += width + 'px';
//console.log(bar.style.width);
}
window.onload = function(){
setInterval(setProgress, 10);
}
I tried using parseInt(), but everytime I console.log() to the window i see the same width. My end goal is for the width to increase by 20
You need to remove px part from width style and then cast string to number before incrementing it:
function setProgress(){
var bar = document.getElementById('progress-bar');
var width = 20;
bar.style.width = Number(bar.style.width.replace('px', '')) + width + 'px';
//console.log(bar.style.width);
}
Make width a global var, like shown below:
var width = 0;
function setProgress(){
var bar = document.getElementById('progress-bar');
width+= 20;
bar.style.width += width + 'px';
//console.log(bar.style.width);
}
window.onload = function(){setInterval(setProgress, 10);}
Also, you should specify the max width to prevent the progress bar moving outside the working area (for example, modifying the increment line: if(width<500) {width+= 20;} else {return;}).
Alternatively, you can use your original solution by adding couple more statements, namely: removing the "px" unit from style property bar.style.width, then parsing it (converting to Number), then incrementing it and then adding "px" (otherwise, "+" operator will cause a concatenation of strings with output like: 20px20px, 20px20px20px, etc). Such alternative solution will slow down the process and put additional load on CPU (thus, it's not recommended).
Hope this may help. Best regards,
The problem is that width returns a string with units.
Instead, consider storing the number of pixels in a variable:
var bar = document.getElementById('progress-bar'),
width = parseFloat(getComputedStyle(bar).width);
setInterval(function() {
width += 20;
bar.style.width = width + 'px';
}, 10);
var bar = document.getElementById('progress-bar'),
width = parseFloat(getComputedStyle(bar).width);
setInterval(function() {
width += 20;
bar.style.width = width + 'px';
}, 200);
#progress-bar {
background: #0f0;
display: inline-block;
}
<div id='progress-bar'>Progress bar</div>
var width = 0;
function setProgress(){
var bar = document.getElementById('bar');
width+= 20;
bar.style.width = width + 'px';
console.log(bar.style.width);
if(width==200){
width=0;
}
}
window.onload = function(){
setInterval(setProgress, 1000);
}
I have a bunch of absolutely positioned elements being generated into a div through javascript.
The positioning of each element differs 2px vertically. IE however adds an extra vertical pixel every 3 elements, then one every 2 elements and then back every 3 elements.
Wait, A pic explains it:
I have coloured the back behaving blocks in red, the correct ones in green.
Chrome renders it correctly (and so does Firefox):
When I use the IE developer tools, I can see that the CSS is set correctly:
I've tried adding zoom:1 to the elements, but that doesn't seem to make a difference.
The code to add the elements is this:
var element = document.createElement("a");
element.style.fontSize = "6pt";
element.style.width = "20px";
element.style.height = "20px";
element.style.position = "absolute";
element.style.backgroundColor = "red";
element.style.zoom = "1";
element.style.display = "block";
var tofs = (columns * 2 + r * 20 - (c * 2));
var lofs = (c * 14 + (r + offset) * 9);
trace(c + "," + r + ": " + lofs + "," + tofs);
element.style.top = tofs + "px";
element.style.left = lofs + "px";
element.style.textIndent = "-10000px";
element.style.overflow = "hidden";
element.innerText = t;
element.selectable = "no";
setBackgroundForSeat(t, element);
target.append(element);
I have tried adjusting the offset every 3 then 2 elements when IE is detected, but that doesn't work: the actual visual difference to the next element becomes 1px instead of the desired 2px (where without the hack it's 3px).
I have run out of ideas. Anybody?
Update: Here's a JS fiddle with the behaviour described. http://jsfiddle.net/uGHDh/5/
I know the IE toolbar is telling you it's setting the CSS correctly, but it might be lying about the actual values. From your code it looks like you will be getting floating point values, and it seems like IE is producing rounding errors when it draws out the objects.
You could try casting the pixel values to an integar before using them, but that might product unwanted results in all the browsers.