Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am working on a website at the moment and have run into a problem with a triangle pattern.
The designer mocked the site up with triangular tiles and patterns :
Please note that I had to remove most of the content to post it here, but there is content on top of the triangular pattern.
I have done some research on how to implement the triangles in HTML,CSS and possibly JS(?) and came up with three possible options:
background-image
clipping divs and positioning them
using svg and positioning this
The problem with a background-image is that some of these tiles will later change on click and show things etc. So they really shouldn't be on a picture
I have started clipping and positioning divs, but this is just taking forever and I am starting to feel like this cannot be the best solution. Loads of fiddling and I think I will later have problems with inconsistencies
I don't have much experience working with svg, but I would have to draw them all one by one and position them as well (right? this is an assumption). Doesn't seem like the best practice approach.
Does anyone have any input on how I could solve this or do I just have to follow through with one of the solutions named above, as there is no quicker way.
I would really appreciate any ideas.
Thanks Anton
If you decide to go with the SVG route then the code to create the triangles can be relatively small. Store the colors in an array of arrays. Store the horizontal and vertical distance between triangles in two variables (e.g. dx and dy). Then loop through the colors array to draw the individual triangles.
JavaScript code...
var svgNS = "http://www.w3.org/2000/svg";
function drawTriangles() {
var svg = document.getElementById("mySvg");
var colors = [
["#0000FF", "#0044FF", "#0088FF", "#00CCFF"],
["#4400FF", "#4444FF", "#4488FF", "#44CCFF"],
["#8800FF", "#8844FF", "#8888FF", "#88CCFF"],
["#CC00FF", "#CC44FF", "#CC88FF", "#CCCCFF"],
];
var n = colors.length;
var m = colors[0].length;
var dx = 100;
var dy = 75;
for (var i = 0; i < n; i++) {
for (var j = 0; j < m; j++) {
var polygon = document.createElementNS(svgNS, "polygon");
var point0 = svg.createSVGPoint();
var point1 = svg.createSVGPoint();
var point2 = svg.createSVGPoint();
if ((i + j) % 2 === 0) {
point0.x = j * dx;
point0.y = i * dy;
point1.x = (j + 1) * dx;
point1.y = (i + 1) * dy;
point2.x = (j + 1) * dx;
point2.y = (i - 1) * dy;
} else {
point0.x = (j + 1) * dx;
point0.y = i * dy;
point1.x = j * dx;
point1.y = (i - 1) * dy;
point2.x = j * dx;
point2.y = (i + 1) * dy;
}
polygon.setAttribute("fill", colors[i][j]);
polygon.points.appendItem(point0);
polygon.points.appendItem(point1);
polygon.points.appendItem(point2);
svg.appendChild(polygon);
}
}
}
drawTriangles();
<svg id="mySvg" width="400" height="225"></svg>
If css shapes are an option, i would recommend to use them.
https://css-tricks.com/examples/ShapesOfCSS/
However you chose to create the boundaries of your containers, if you embed the svg directly into the html, you can access all the elements the same way you access html elements, and with them you can get their vertices. This way you could use that information to create the shapes.
The downside of that approach is that it is highly depending on javascript, if it is disabled or fails, the complete layout will fail, too. But you can react on layout changes at runtime.
To overcome this you might be able to process the svg on the server, but there you are missing out the final dimensions, what might not be problem if you use percentage values to position your content containers, but a huzzle to code.
All in all, if got this right, creating such a layout where content is arranged in triangles will need a lot of code in each case.
If the page will stay small and not much content be assigned, than doing everything by hand might be faster.
Related
I would like to create divs with complex waves, I'm coming across a lot of tutorials and I tried a lot of things but I can not do it. What is the best way to make waves and the background goes around and stops at the wave? What is the best/simplest way, I heard about the SVG but no skill with that. Is it complicated to realize? I wish I could draw curves and change the background accordingly as on this WordPress theme:
https://www.elegantthemes.com/blog/theme-releases/shape-dividers
I wish I could do that:
http://www.zupimages.net/viewer.php?id=19/22/jr0r.png
I have to learn SVG ? or use illustrator, too complicated directly in CSS if I have several waves. A software like an illustrator to do that for free with SVG exist?
and then do the rest of my style with bootstrap 4 etc? ...thank you
Normally you can do this using Perlin noise. However you can do it also by setting a number of points with successive x and random y on the svg canvas, and connecting the points with Béziers.
let w = 1000;
let h = 300;
svg.setAttributeNS(null,"viewBox",`0 0 ${w} ${h}`)
let n = 18; //number of points
let points = [];// the points array used to draw the curve
// add points to the points array
for(let x=0; x <= w; x+= w/n){
let y = h - Math.random()*h;
points.push({x:x,y:y})
}
// a function to connect all the points in the points array with beziers
function connect(points) {
let d = "";// the d attribute for the path
// move to the first point of the array
d+= `M${points[0].x}, ${points[0].y}`;
//build the path
for (var i = 1; i < points.length - 2; i++) {
var cp = {};
cp.x = (points[i].x + points[i + 1].x) / 2;
cp.y = (points[i].y + points[i + 1].y) / 2;
d+=`Q${points[i].x},${points[i].y} ${cp.x},${cp.y}`
}
//the last curve
let index = points.length-2
d+=`Q${points[index].x},${points[index].y} ${points[index + 1].x},${points[index + 1].y}`;
//close the path
d+=`V${h}H0z`
return d;
}
//set the attribute `d` for the wave
wave.setAttributeNS(null,"d",connect(points))
svg{border:1px solid}
<svg id="svg" >
<path id="wave" />
</svg>
I tried this before, just by using an image as border. You can create an image with a wavy border and play with transparency so you get the effect you need.
I am trying to replicate this effect: http://hakim.se/experiments/html5/trail/03/
I have this as a Particle constructor:
function Particle(x, y) {
this.x = x;
this.y = y;
this.radius = 4;
this.color = '#f0f';
this.speed = 15;
this.angle = 0;
}
And I'm using this loop to animate all particle instances:
for (var i = 0, len = particles.length; i < len; i++) {
var dx = mouse.x - particles[i].x,
dy = mouse.y - particles[i].y,
angle = Math.atan2(dy, dx);
particles[i].vx = Math.cos(angle) * particles[i].speed;
particles[i].vy = Math.sin(angle) * particles[i].speed;
particles[i].x += particles[i].vx;
particles[i].y += particles[i].vy;
particles[i].draw(ctx);
}
The particles follow the mouse, but reach the cursor and start flickering around it, which is not a desired behaviour. I'd like to circle around the cursor, as in the example.. The interesting part is that if I set the particle.speed to something like 30 and add 1000 to the angle, the particles rotate around the cursor, but really fast and ruin the effect...
You can see a live example here: http://codepen.io/gbnikolov/pen/EwafI
All suggestions are more then welcome, thanks in advance!
P.S. I know that the code for the pointed example is easily findable, but I'm relatively new to javascript and I'm not that good at reading other people code and can't quite understand the logic behind it..
Currently the target of your particles is the mouse cursor. But that's not the target you want. You want a target that's moving around your cursor. And you want for every particle a different target, so they don't hover all at the same place.
There are also some other things that the original does and you don't:
in the original, the particle speed depends on the distance to the target
it seems they can't change the direction instantly, but change the direction of their movement relatively slowly.
Using some code I found online has helped me create a zoom function for a program I am attempting to make. It is to make a map that allows a user to mark points. Currently the code scales in on the map image alone but I cant get the point icons to realign to where they originally where. I cant workout the maths of it.
Code to zoom in and out
if (mev.shiftKey) {
image.scaleX = Math.max(scaleFactor*image.scaleX, minScale);
image.scaleY = Math.max(scaleFactor*image.scaleY, minScale);
}
if (mev.ctrlKey) {
image.scaleX = Math.min(1/scaleFactor*image.scaleX, maxScale);
image.scaleY = Math.min(1/scaleFactor*image.scaleY, maxScale);
mat = image.transform.matrix.clone();
MatrixTransformer.matchInternalPointWithExternal(mat,internalCenter,externalCenter);
image.transform.matrix=mat;
This allows the image to scale up with the following factors
public var scaleFactor:Number = 0.8;
public var minScale:Number = 0.25;
public var maxScale:Number = 2.0;
The problem occurs when I try to move the pointer icons that are overlaid on this image. They are not to grow or shrink at the moment but they I cant get the maths to get them to move the correct number of pixels away from the mouse location so that they are still in line. Currently I am using the following formulas
//decrease zoom
stage.getChildAt(i).x = stage.getChildAt(i).x * scaleFactor;
//increase zoom
stage.getChildAt(i2).x = stage.getChildAt(i2).x / scaleFactor;
Any thoughts ? Code I am using came from
http://www.flashandmath.com/howtos/zoom/
Quite a few elements missing from the question like the moving map underneath. Anyway now that it's sorted out ...
If you are not a math genius and can't tackle 2 math formulas at the same time then don't and tackle them one by one then combine them. Once again don't use the x,y property of point for calculation but create specific property (like in a custom class for example). I will name them here origin for convenience.
Given a point with origin property of x:100, y:200, its position on the map is (assuming map is top left coordinate, if not adapt accordingly):
point.x = map.x + point.origin.x;
point.y = map.y + point.origin.y;
the positioning is solved now you need to solve for scale which is easy:
point.x = point.origin.x * scaleFactor;
point.y = point.origin.y * scaleFactor;
Both systems are solved now you can combine the two:
point.x = map.x + (point.origin.x * scaleFactor);
point.y = map.y + (point.origin.y * scaleFactor);
I'm trying to zoom a DisplayObject into a certain point. I figured it would be easy, but I've spent a day now trying to figure it out.
Basically, I think this should work. Emphasis on should.
//newPoint is the point being centered. There is no initial scaling, so I do not need to compensate for that (yet)
//scale is the zoom level
//container is the parent of the obj
//obj is the object being scaled/panned
var p:Point = new Point(
( this.container.width - this.obj.width * scale + newPoint.x * scale ) / 2,
( this.container.height - this.obj.height * scale + newPoint.y * scale ) / 2
);
this.obj.scaleX = this.obj.scaleY = scale;
this.obj.x = p.x;
this.obj.y = p.y;
It centers the point if scale is 1, but it gets further and further away from center as you increase the scale. I've tried dozens of different methods. This method, which I have seen on several sites, produced the same exact results. Anyone have any idea how to get this to work?
EDIT 10-1-12:
As a followup, I took the code snippet that LondonDrugs_MediaServices provided as a basis for my original issue. I needed to be able to zoom to a specific point at a specific scale relative to the unscaled image (think how Google Maps zooms to a specific location). To do this, I had to center my image on the point before running the translation code. I've posted the additional code below. For other uses (pinch to zoom, scrolling, and double click), I used the code provided by Vesper, which worked quite well.
//obj is the object being translated
//container is its parent
//x and y are the coordinates to be zoomed to, in untranslated scaling
//obj.scaleX and obj.scaleY are always identical in my class, so there is no need to account for that
//calculates current center point, with scaling
var center:Point = new Point( ( this.container.width - this.obj.width * this.obj.scaleX ) / 2, ( this.container.height - this.obj.height * this.obj.scaleX ) / 2 );
//calulcates the distance from center the point is, with scaling
var distanceFromCenter:Point = new Point( this.obj.width * this.obj.scaleX / 2 - x * this.obj.scaleX, this.obj.height * this.obj.scaleX / 2 - y * this.obj.scaleX );
//center the object on that specific point
this.obj.x = center.x + distanceFromCenter.x;
this.obj.y = center.y + distanceFromCenter.y;
var mat:Matrix=new Matrix();
mat.translate(-p.x,-p.y);
mat.scale(desiredScale,desiredScale);
mat.translate(p.x,p.y);
yourObject.transform.matrix=mat;
The core point is that scaling is done around (0,0), but you can do it with matrix that describes affine transformations. You first make an empty matrix (that is, a matrix that doesn't transform), then apply a set of transformations to it. First, place a desired point at (0,0) by translating by -1*coordinates, then scale, then translate back.
hie guys....
thank's your comments...
i found the answer...
code :
gambar.addEventListener(TransformGestureEvent.GESTURE_ZOOM , onZoom);
function onZoom(event:TransformGestureEvent):void {
var locX:Number=event.localX;
var locY:Number=event.localY;
var stX:Number=event.stageX;
var stY:Number=event.stageY;
var prevScaleX:Number=gambar.scaleX;
var prevScaleY:Number=gambar.scaleY;
var mat:Matrix;
var externalPoint=new Point(stX,stY);
var internalPoint=new Point(locX,locY);
gambar.scaleX *= event.scaleX;
gambar.scaleY *= event.scaleY;
if(event.scaleX>1 && gambar.scaleX>6){
gambar.scaleX=prevScaleX;
gambar.scaleY=prevScaleY;
}
if(event.scaleY>1 && gambar.scaleY>6){
gambar.scaleX=prevScaleX;
gambar.scaleY=prevScaleY;
}
if(event.scaleX<1 && gambar.scaleX<0.8){
gambar.scaleX=prevScaleX;
gambar.scaleY=prevScaleY;
}
if(event.scaleY<1 && gambar.scaleY<0.8){
gambar.scaleX=prevScaleX;
gambar.scaleY=prevScaleY;
}
mat=gambar.transform.matrix.clone();
MatrixTransformer.matchInternalPointWithExternal(mat,internalPoint,externalPoint);
gambar.transform.matrix=mat;
}
The matrix answer is absolutely correct, but if you happen to be a Club GreenSock member you can get some nice functionality with very simple code with the TransformAroundPointPlugin
http://www.greensock.com/as/docs/tween/com/greensock/plugins/TransformAroundPointPlugin.html
You can see an example in the plugin explorer here:
http://www.greensock.com/tweenlite/#plugins
I use this to tween all my zooms and have much better performance than when I tried to do this manually. IMO the whole library is worth it's weight in gold (and no I have no connection other than liking the library). If you need any of the other features I'd look into it. It also has the ThrowProps plugin ( http://www.greensock.com/throwprops/ )which is very important if you are going to have a bounding box on mobile that you want to have a smooth return into the boundaries.
Set obj.x to -p.x and obj.y to -p.y, set the container scaleX and scaleY to the desired value and add p.x to the container x and p.y to the container y. Done!
So I have a circle of planes which get constructed as:
plane.x = Math.cos(angle) * radius;
plane.z = Math.sin(angle) * radius;
plane.rotationY = (-360 / numItems) * i - 90;
which calculates how many angular slices there are for total number of planes (rotationY) and places each plane into it's place on a circle of radius.
then to update their rotation around the circle I have:
var rotateTo:Number = (-360 / numItems) * currentItem + 90;
TweenLite.to(planesHolder, 1, { rotationY:rotateTo, ease:Quint.easeInOut } );
as you can see planes are circling and each is oriented 90 degrees out from the circle.
I'm using this as a reference - it's pretty much that: http://papervision2.com/a-simple-papervision-carousel/
Now, what I'd like to find out is how could I calculate degree of orientation for each individual plane to always face camera without normal, if it's possible at all. I've tried plane.LookAt(camera), but that doesn't work. Basically every plane should have orientation as the one facing camera in the middle.
Somehow I think I can't modify that example from link to do that.
edit: OK I answered my own question after I wrote it. Helps to read your own thoughts written. So as I'm orienting planes individually and rotating them all as a group, what I did after tween of the group in code above, was to loop through each plane and orient it to the Y orientation of the forward plane as so:
for (var i:int = 0; i < planes.length; i++) {
TweenLite.to(planes[i], 1, { rotationY:(-360 / numItems * rotoItem - 90), ease:Quint.easeInOut } );
}
rotoItem is the one at the front. Case closed.
OK I answered my own question after I wrote it. Helps to read your own thoughts written. So as I'm orienting planes individually and rotating them all as a group, what I did after tween of the group in code above, was to loop through each plane and orient it to the Y orientation of the forward plane as so:
for (var i:int = 0; i < planes.length; i++) {
TweenLite.to(planes[i], 1, { rotationY:(-360 / numItems * rotoItem - 90), ease:Quint.easeInOut } );
}
rotoItem is the one at the front. Case closed.