Setting div Background using Trianglify - javascript

I have some problems using the Trianglify plugin. I would like to use it to set the background of a div. How can I do this? I couldn't find a proper example.
Here's my sample code:
<script>
var pattern = Trianglify({
width: window.innerWidth,
height: window.innerHeight
});
document.body.appendChild(pattern.canvas())
</script>
Also, can I have divs with different backgrounds that come from Trianglify?

One DIV
Here is an example of setting a DIV background to a Trianglify pattern. It cheats a bit and sets the DIV child node to the pattern but it should work for you.
var something = document.getElementById('something');
var dimensions = something.getClientRects()[0];
var pattern = Trianglify({
width: dimensions.width,
height: dimensions.height
});
something.appendChild(pattern.canvas());
The DIV has an id of something and the CSS styles are set on the div for height and width.
Working example JSFiddle: http://jsfiddle.net/u55cn0fh/
Multiple DIVs
We can easily expand this for multiple DIVs like so:
function addTriangleTo(target) {
var dimensions = target.getClientRects()[0];
var pattern = Trianglify({
width: dimensions.width,
height: dimensions.height
});
target.appendChild(pattern.canvas());
}
JSFiddle: http://jsfiddle.net/u55cn0fh/1/
Multiple DIVs as a true background-image
The above are simply appending the pattern to the DIV as a child node instead of setting it as a background. The good news is that we can indeed use the background-image CSS property like so:
function addTriangleTo(target) {
var dimensions = target.getClientRects()[0];
var pattern = Trianglify({
width: dimensions.width,
height: dimensions.height
});
target.style['background-image'] = 'url(' + pattern.png() + ')';
}
JSFiddle: http://jsfiddle.net/abL2kc2q/

I'm pretty late to this answer, but I think it's still valuable:
If you aren't satisfied with using pattern.png() to generate a PNG version (like I wasn't), then you can also use pattern.svg() to set a SVG background with a little more work.
I always tend to lean towards using SVG backgrounds as typically they are crisper. In a test case I ran, using the SVG version also saved bits (although it's relative because sending a Trianglify background is a bit of a burden to begin with).
Characters in the base64 SVG encoding: 137284
Characters in the base64 PNG encoding: 195288
Converting the SVG to a base64 encoding then setting it as the background image can be achieved as follows:
// Create the Trianglify pattern
var pattern = Trianglify({
cell_size: 30,
variance: 0.75,
x_colors: 'random',
y_colors: 'match_x',
palette: Trianglify.colorbrewer,
stroke_width: 1.51,
});
// Serialize the SVG object to a String
var m = new XMLSerializer().serializeToString(pattern.svg());
// Perform the base64 encoding of the String
var k = window.btoa(m);
// Query the element to set the background image property
var element = document.getElementsByTagName('header')[0];
// Set the background image property, including the encoding type header
element.style.backgroundImage = 'url("data:image/svg+xml;base64,' + k + '")';
Hope this helps!

IN my case I had to use a class to use multiple instances of the same background image :
var obj = {
'trianglifiedlightblue': ['#a5cade', '#b7d5e5', '#d5e6f0', '#006ab4', '#e8f2f7', '#cee2ed'],
'trianglifiedbleu': ['#004e83', '#005f9f', '#004879', '#006ab4', '#004777', '#005f9f'],
'trianglifiedviolet': ['#680036', '#830447', '#e62f8e', '#c76c9b'],
'trianglifiedrouge': ['#5f0308', '#851117', '#cf363f', '#e86d74']
};
function addTriangle(classname) {
targets = document.getElementsByClassName(classname);
for (i = 0; i < targets.length; i++) {
target = targets[i];
if (target != null) {
var dimensions = target.getClientRects()[0];
var pattern = Trianglify({
width: dimensions.width,
height: dimensions.height,
x_colors: obj[classname],
cell_size: 100 + Math.random() * 200
});
target.style['background-image'] = 'url(' + pattern.png() + ')';
}
}
}
addTriangle('trianglifiedlightblue');
addTriangle('trianglifiedbleu');
addTriangle('trianglifiedviolet');
addTriangle('trianglifiedrouge');
div {
height: 100px;
width: 500px;
margin:10px;
float:left;
background:#efefef;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/trianglify/0.2.1/trianglify.min.js"></script>
<div class="trianglifiedlightblue"></div>
<div class="trianglifiedbleu"></div>
<div class="trianglifiedviolet"></div>
<div class="trianglifiedrouge"></div>
or if you prefer to keep an ID you can try this :
http://jsfiddle.net/thecpg/Lecdhce6/10/

Related

How do I have a background image change within a div using JS?

My issue is I am trying to get a background image to change every second within the first div of a travel blog I have been working on using JS. I am also having text display on top of the image. There are couple tutorials on YouTube but they just arent working for me.
my css is:
#title{
background-image: url("../images/Nature5.jpg");
background-size: cover;
padding-top: 350px;
padding-bottom: 350px;
}
And my Javascript is:
var changingImages = document.querySelector('title');
var images = [
"url('../images/Nature1.jpg')",
"url('../images/Nature2.jpg')",
"url('../images/Nature3.jpg')",
"url('../images/Nature4.jpg')",
"url('../images/Nature5.jpg')",
"url('../images/Nature6.jpg')"
]
setInterval( function () {
var bg = images[Math.floor(Math.random() * images.length)]
title.style.backgroundImage = bg;
},1000)
Perhaps the images are too large or maybe I'm just too new to JS.
Any help is appreciated!
I tried placing the variabule "changingImages" within the function also changing the "title.style.backgroundImage = bg;" to be more spacific.
please try this one
add class selector in query selector argument '.title'
var changingImages = document.querySelector('.title'); // the change
var images = [
"url('../images/Nature1.jpg')",
"url('../images/Nature2.jpg')",
"url('../images/Nature3.jpg')",
"url('../images/Nature4.jpg')",
"url('../images/Nature5.jpg')",
"url('../images/Nature6.jpg')"
]
setInterval( function () {
var bg = images[Math.floor(Math.random() * images.length) + 1] // the change
changingImages.style.backgroundImage = bg; // the change
},1000)
hope this work

Changing Height in CSS with Variable in JavaScript

So I'm trying to make the height of my DIV's respond to the width of the window. The code:
var w = window.innerWidth;
var mathW = parseInt(w);
var divHeight = mathW*0.16;
document.getElementById('demoDiv').style.height = divHeight;
With the CSS being:
#demoDiv {
margin: auto;
background-color: red;
width: 100%;
height: 50px; //just to start with SOMETHING
}
Obviously I'm having trouble with that! I've played around with it and definitely can change the height if I just use regular integers, but even using parseInt('divHeight') did nothing for me!
You are calucalting the height in a correct way. But in order to set the height you need to add dimension to the value (say px).
You dont need to do parseInt as window.innerWidth is a property with typeof number.
var w = window.innerWidth;
var divHeight = mathW*0.16;
document.getElementById('demoDiv').style.height = divHeight+"px";
What stops you from applying a pure CSS solution?
#demoDiv {
height: 16vw;
}
Requires no Javascript, is much shorter and performs faster, and no need to apply any resize handler when window size changes.

Zoom inside of a div, changing the inner elements but not the div itself

I am looking for a way to zoom into a div element. Since this question did not provide some code example, I decided to post the following.
This jsfiddle already helped, but as you can see in my adapted jsfiddle, the whole div scales. I just want the image inside to scale. the div should have an overflow if zoomed in (also scroll bars).
Is this possible without including other scripts e.g. panzoom?
HTML
<div id="pane">
<img src="http://i.stack.imgur.com/oURrw.png">
</div>
JavaScript
$('#pane').bind('mousewheel DOMMouseScroll', function(e){
var stage = $(this);
scaleData = getZoom(stage);
if ( e.originalEvent.detail < 0 ){
setZoom( scaleData.curScale * '.9', stage );
}
else{
setZoom( scaleData.curScale * '1.1', stage );
}
});
function setZoom(scale, el){
scale = Math.round(scale*10)/10;
el.attr({
style:
'zoom: '+scale+';'+
'-webkit-transform: scale('+scale+');'+
'-moz-transform: scale('+scale+');'+
'-o-transform: scale('+scale+');'+
'-ms-transform: scale('+scale+');'+
'transform: scale('+scale+');'
});
}
function getZoom(el){
var curZoom = el.css('zoom');
var curScale = el.css('transform') ||
el.css('-webkit-transform') ||
el.css('-moz-transform') ||
el.css('-o-transform') ||
el.css('-ms-transform');
if ( curScale === 'none' ){
curScale = 1;
}else{
//Parse retarded matrix string into array of values
var scaleArray = $.parseJSON(curScale.replace(/^\w+\(/,"[").replace(/\)$/,"]"));
//We only need one of the two scaling components as we are always scaling evenly across both axes
curScale = scaleArray[0];
}
return { curZoom: curZoom, curScale: curScale };
}
CSS
div#pane{
height: 20em;
margin: auto;
background-color: #ffffff;
overflow: scroll;
position: relative;
z-index: 0;
}
Thank you
If I understand correctly the solution is to change the 2nd line of the JS you provided in a JSFiddle to:
var stage = $(this).find('img');
I just included .find('img') to the end of what you had there. Previously you were zooming the entire div, now it zooms just the img tag.

JS/jQuery fit all images inside div (without whitespace)

I have a div call it #container,
Inside this #container I have n amount of img tags call it images
n can be 2, 10, 40 and so on.
I am wondering how I can fit n amount of images inside a #container to close all white spaces stretch the images. Quality doesn't matter
This is what I tried until now:
var amount = $("#container > img").length;
var amount_w = amount*200; //200 width of 1 image
var amount_h = amount*130; //120 height image
var refH = $("#container").height();
var refW = $("#container").width();
var refRatio = refW/refH;
$("#container img").each(function(){
$(this).height((amount_h-130)-refH);
$(this).width((amount_w-230)-refW);
});
First of all, it IS possible to achieve what you need even while maintaining the aspect ratio of the images - however the row height will be calculated, but it is not a trivial task (well, at least not as trivial as a single line formula).
There is a jQuery plugin called jPictura which I have developed. I believe the plugin does exactly what you need.
Here is a working fiddle.
You can find the plugin source codes and documentation on GitHub.
Simple example how to use the plugin:
$(document).ready(function () {
$('#my-gallery').jpictura({
layout: { itemSpacing: 0, justifyLastRow: true, idealRowHeight: 200}
});
});
itemSpacing - amount of space between the images in pixels
justifyLastRow - if true, the images in last row will be stretched to take the full width of the row
idealRowHeight - The desired height of the rows in pixels. The plugin will do its best to arrange the items so the row heights are as close as possible to this value.
there are a lot more options documented on GitHub
Beside the JS stuff that calculates the correct widths and heights of the images, there is one more thing to be considered regarding the blank space between images. Images are by default inline-blocks which means they behave like words and words do have some white space inbetween, right? Make them display: block; float: left; or use the flex box layout to get rid of the blank space. The plugin uses float: left; by default.
I created something that might interest you
var container = $('#container');
var height = container.outerHeight();
var width = container.outerWidth();
function populate(n){
var rem_items = n;
var rows = Math.round(Math.sqrt(n));
var row_items = Math.ceil(n/rows);
for (var i=0; i<rows; i++){
// this prevents us from generating a lonely single box in a row
if( (rem_items%(rows-i))===0 ){
row_items = rem_items/(rows-i);
}
if(rem_items<row_items){
row_items = rem_items;
}
rem_items = rem_items-row_items;
for (var j=0; j<row_items; j++){
var img_height = height/rows;
var img_width = width/row_items;
var img_left = j*img_width;
var img_top = i*img_height;
var img = $('<div class="cell"></div>');
img.css({
width: img_width,
height: img_height,
left: img_left,
top: img_top
});
container.append(img);
}
}
}
populate(40);
https://jsfiddle.net/jLq4hgaa/1/
Basically, it calculates the "most balanced" distribution of the images horizontally and vertically.
It does what you're asking for in the plainest sense. It distributes images/containers inside a container evenly regardless of aspect ratio.
$(document).on("pageload",function(){
$('.container').addClass('stretch');
});
Then make a css element called "stretch" defining width:100%
Height:100% and if need be define layout, i.e relative

how to center and make various images sizes fit in a container

I'm using bxslider to have a carousel of images. The thing is though, the images it receives to display are of somewhat unpredictable sizes. The container size is 243x243. And we know that no image will have a side smaller than 243. So...I'd like to center the image in the container. And either zoom in until the shorter of the two dimensions (L vs W) fills the container at 243, and the longer dimension overflow is hidden.
For the images I'm working with, doing this will be perfect for getting the important details of the picture in the frame.
But I'm having trouble...
I've tried the following to center the picture in the frame:
jQuery(".bx-container").each(function() {
var img_w = jQuery(this).children("img").width();
var img_h = jQuery(this).children("img").height();
var pos_top = (img_h - containerHeight) / 2;
var pos_left = (img_w - containerWidth) / 2;
var pos_top = (243 - img_h) / 2;
var pos_left = (243 - img_w) / 2;
jQuery(this).children("img").css({
'top' : pos_top + 'px',
'left' : pos_left + 'px'
});
});
And I've tried this to position not square images into the frame:
jQuery(".bx-container").each(function(){
var refRatio = 1;
var imgH = jQuery(this).children("img").height();
var imgW = jQuery(this).children("img").width();
if ( (imgW/imgH) < refRatio ) {
jQuery(this).addClass("bx-portrait");
} else {
jQuery(this).addClass("bx-landscape");
}
});
});
I've messed with both scripts and the css but I just can't seem to get it work. It either centers but doesn't resize right. Or resizes but centers wrong. Or does both wrong.
Here's the jsfiddle: http://jsfiddle.net/vgJ9X/298/
Could someone help me out?
Thanks!
EDIT:
New jsfiddle...the portrait ones work right. The landscape images still squish. :(
http://jsfiddle.net/vgJ9X/307/
EDIT:
I THINK it has something to do with relatively positioned elements not being allowed to overlap. Trying to find a fix. If anyone knows, edit the last fiddle I posted.
jQuery(".bx-container img").each(function () {
var w = jQuery(this).width();
var h = jQuery(this).height();
if (w > h) $(this).addClass('bx-landscape');
else $(this).addClass('bx-portrait');
});
Check this Updated JSFiddle
Update
jQuery(".bx-container img").each(function () {
var w = jQuery(this).width();
var h = jQuery(this).height();
if (w > h){
$(this).addClass('bx-landscape');
var trans= -243/2;
$(this).css('-webkit-transform','translateZ('+trans+'px)');
}
else if(h > w){
$(this).addClass('bx-portrait');
var trans= -243/2;
$(this).css('-webkit-transform','translateY('+trans+'px)');
}
});
check this JSFiddle
Update of Update
Found the issue with landscape, the plugin is setting max-width:100%; overriding it with max-width:none; fixes the issue...
Update Of Updated Fiddle
Try this:
img{
position:relative;
height:100%;
width:300px;
}
Simple an clean.
Demo: http://jsfiddle.net/vgJ9X/302/
I did a couple things to your jsfiddle.
First I changed the order of your resize and center functions, so the resize comes first. This way, the smaller images get resized, then centered. I also uncommented the first portion of your code.
You also had a couple of errors in your css. There was an extra closing bracket after img style declaration. Your .bx-portrait img and .bx-landscape img declarations were set to 100%px;.
Update:
Change the css in your two .bx classes to:
.bx-portrait img {
height: 100%;
width: auto;
}
.bx-landscape img {
height: auto;
width: 100%;
}
And add a clearfix to your ul:
.bxslider:after {
content: '';
clear: both;
display: table;
padding: 0;
margin: 0;
}
The height is clipping because .bx-viewport has a set height of 243px but also has a 5px border, which makes the actual internal height 233px. You'll need to make the height 253px to account for the 10px of border. This is why they don't look centered vertically.
DEMO
Why don't you just use background images instead and center them. Here is a demo from your original code
http://jsfiddle.net/8y8df/
If you want to show the full size image, just remove the background-size:contain; from the css.

Categories