External Javascript Libraries (cdnjs) not being reached by html code - javascript

I have been trying to add some html and javascript to my website so users can draw some shapes. I found a really good sample to work from on JS Fiddle. When I run the code on JSFiddle, it works perfectly, but when I ran it myself on my browser (I tried Edge, Firefox, and Chrome) it did not work.
When I ran it myself, I included all the scripts and css into one html file because thats the only way to add it to my Wix website. The scripts (local javascript, and external cdn libraries) where together in the body section of html. All the tutorials I found make it seem like it's OK to use the CDN libraries. I'm positive my issue has something to do with the connection to the CDN libraries, so how would I fix it?
Here is code:
var roof = null;
var roofPoints = [];
var lines = [];
var lineCounter = 0;
var drawingObject = {};
drawingObject.type = "";
drawingObject.background = "";
drawingObject.border = "";
function Point(x, y) {
this.x = x;
this.y = y;
}
$("#poly").click(function () {
if (drawingObject.type == "roof") {
drawingObject.type = "";
lines.forEach(function(value, index, ar){
canvas.remove(value);
});
//canvas.remove(lines[lineCounter - 1]);
roof = makeRoof(roofPoints);
canvas.add(roof);
canvas.renderAll();
} else {
drawingObject.type = "roof"; // roof type
}
});
// canvas Drawing
var canvas = new fabric.Canvas('canvas-tools');
var x = 0;
var y = 0;
fabric.util.addListener(window,'dblclick', function(){
drawingObject.type = "";
lines.forEach(function(value, index, ar){
canvas.remove(value);
});
//canvas.remove(lines[lineCounter - 1]);
roof = makeRoof(roofPoints);
canvas.add(roof);
canvas.renderAll();
console.log("double click");
//clear arrays
roofPoints = [];
lines = [];
lineCounter = 0;
});
canvas.on('mouse:down', function (options) {
if (drawingObject.type == "roof") {
canvas.selection = false;
setStartingPoint(options); // set x,y
roofPoints.push(new Point(x, y));
var points = [x, y, x, y];
lines.push(new fabric.Line(points, {
strokeWidth: 3,
selectable: false,
stroke: 'red'
}).setOriginX(x).setOriginY(y));
canvas.add(lines[lineCounter]);
lineCounter++;
canvas.on('mouse:up', function (options) {
canvas.selection = true;
});
}
});
canvas.on('mouse:move', function (options) {
if (lines[0] !== null && lines[0] !== undefined && drawingObject.type == "roof") {
setStartingPoint(options);
lines[lineCounter - 1].set({
x2: x,
y2: y
});
canvas.renderAll();
}
});
function setStartingPoint(options) {
var offset = $('#canvas-tools').offset();
x = options.e.pageX - offset.left;
y = options.e.pageY - offset.top;
}
function makeRoof(roofPoints) {
var left = findLeftPaddingForRoof(roofPoints);
var top = findTopPaddingForRoof(roofPoints);
roofPoints.push(new Point(roofPoints[0].x,roofPoints[0].y))
var roof = new fabric.Polyline(roofPoints, {
fill: 'rgba(0,0,0,0)',
stroke:'#58c'
});
roof.set({
left: left,
top: top,
});
return roof;
}
function findTopPaddingForRoof(roofPoints) {
var result = 999999;
for (var f = 0; f < lineCounter; f++) {
if (roofPoints[f].y < result) {
result = roofPoints[f].y;
}
}
return Math.abs(result);
}
function findLeftPaddingForRoof(roofPoints) {
var result = 999999;
for (var i = 0; i < lineCounter; i++) {
if (roofPoints[i].x < result) {
result = roofPoints[i].x;
}
}
return Math.abs(result);
}
.canvas {
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<button id="poly" title="Draw Polygon" ">Draw Polygon </button>
<label style="color:blue"><b>Press double click to close shape and stop</b></label>
<canvas id="canvas-tools" class="canvas" width="500" height="500"></canvas>
EDIT
So, in the html file I put everything inside the body tag. The libraries are also included before the javascript. I get the error "Unable to get property 'x' of undefined or null reference" when I double-click to close the shape. I'm positive its because no points are added when I click in the canvas

Wix does not allow using Cloudflare. The following link has more detail.
https://support.wix.com/en/article/request-cloudflare-support
Wix has some limited API to work with HTML elements
https://support.wix.com/en/article/corvid-working-with-the-html-element
if you want to run it on a separate page (not on wix) and scripts are loaded try to wrap your javascript code in :
<script>
$(function() {
//your code here
var roof = null;
var roofPoints = [];
var lines = [];
var lineCounter = 0;
var drawingObject = {};
...
...
});
</script>

Related

"Exception has occured: TypeError: Arrary.prototype.forEach called on null or undefined" in p5.js file

After trying to run some p5.js code in Visual Studio Code, I came upon this error. My HTML Code is below, and I copied and pasted it straight from the P5 editor:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
My javascript code is below, and when running in p5, no errors come up:
var numOfFood;
var foodList;
var numOfSlimes;
var slimesList;
function setup() {
createCanvas(400, 400);
numOfFood = prompt("Enter the amount of food that should be spawned: ");
numOfSlimes = prompt("Enter the amount of slimes to be spawned: ");
foodList = [];
slimesList = [];
background(220);
rect(25, 25, width - 50, height - 50);
spawnFood(numOfFood);
initializeSlimes(numOfSlimes);
}
// SLIME
Slime = function (x, y) {
this.x = x;
this.y = y;
}
Slime.prototype.draw = function () {
ellipse(this.x, this.y, 12, 12);
}
Slime.prototype.assignFood = function (index) {
this.food = foodList[index];
this.foodIndex = index;
}
// SLIME
// HAWK
Hawk = function (x, y) {
Slime.call(this, x, y);
this.type = "HAWK";
}
Hawk.prototype = Object.create(Slime.prototype);
//HAWK
// DOVE
Dove = function (x, y) {
Slime.call(this, x, y);
this.type = "DOVE";
}
Dove.prototype = Object.create(Slime.prototype);
// DOVE
// FOOD
Food = function (x, y) {
this.x = x;
this.y = y;
}
Food.prototype.draw = function () {
ellipse(this.x, this.y, 10, 10);
}
Food.prototype.assignSlime = function (firstSlime = null, secondSlime = null) {
this.firstSlime = firstSlime;
this.secondSlime = secondSlime;
}
// FOOD
spawnFood = function(food) {
fill(229, 246, 88);
var factors = []
var differences = []
for (let i = 1; i < food; i++) {
var value = food/i;
if (value != Math.floor(value)) {
continue;
}
factors.push([value, i]);
differences.push(abs(value - i));
}
var currentMinIndex = 0;
for (let i = 0; i < differences.length; i++) {
if (differences[i] < differences[currentMinIndex]) {
currentMinIndex = i;
}
}
for (let x = 50; x < 350; x += 300/factors[currentMinIndex][0]) {
for (let y = 50; y < 350; y += 300/factors[currentMinIndex][1]) {
var myFood = new Food(x, y);
foodList.push(myFood);
myFood.draw();
}
}
}
initializeSlimes = function (slimes) {
var tempx = 0;
var tempy = 0;
fill(67, 163, 235);
for (let i = 25; i < 375; i+= 375/(slimes / 4)) {
let mySlime = new Slime(i, 12.5); mySlime.draw(); slimesList.push(mySlime);
}
for (let i = 25; i < 375; i+= 375/(slimes / 4)) {
let mySlime = new Slime(i, 387.5); mySlime.draw(); slimesList.push(mySlime);
}
for (let i = 25; i < 375; i+= 375/(slimes / 4)) {
let mySlime = new Slime(12.5, i); mySlime.draw(); slimesList.push(mySlime);
}
for (let i = 25; i < 375; i+= 375/(slimes / 4)) {
let mySlime = new Slime(387.5, i); mySlime.draw(); slimesList.push(mySlime);
}
}
However, when I try to run this in VSCode, chrome opens to try and run the file, but then the window switches back to VSCode, and it shows me:
My error code (I don't have enough rep to embed a picture yet)
If anybody knew how to fix this, I would be extremely grateful. Is this a problem in my code, or is this a problem with the p5 library?
Could you show where the error appears in your javascript file rather than in the p5.js library itself?
Otherwise, I don't even see a call to Array.forEach() in your code snippit, did you make sure to paste all of the code you're running? Or since your p5.js file isn't even being loaded in your index.html, are you trying to run the p5.js file itself? That won't work, make sure you're running your index.html file.
I tried running your index.html using a copy of p5.js in the source folder and copied all of your code into a sketch.js file, and I was able to run it through VSCode. Let me know if this helps at all or if you have any other information that could help with fixing your problem!

How to link P5.js setup and draw with html canvas?

I am sure this is a very simple thing to do, but I am stuck here.
Here is the situation:
I have an HTML page with a div and a canvas element(not sure if I need this)
Also I have two javascript files using p5.js with setup and draw funtions where I draw my content on a canvas I create with createCanvas.
The other js file contains an object.
The problem is - I can get the animation to show on the HTML page, but not inside the div and/or canvas.
Image for a clearer picture:
HTML and JS comunication
HTML:
<html>
<head>
<meta charset="utf-8">
<title>Fractals</title>
<script language="javascript" type="text/javascript" src="libs/p5.js"></script>
<script language="javascript" src="libs/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script language="javascript" type="text/javascript" src="branch.js"></script>
<style>
body {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div>
<canvas id="fractal" height="197" width="333" style=" width:333;height:197;"></canvas>
</div>
</body>
</html>
JS sketch:
var tree = [];
var x;
var y;
function setup() {
createCanvas(333,197);
var a = createVector(width / 2, height);
var b = createVector(width / 2, height - 50);
var root = new Branch(a, b);
tree[0] = root;
for (var t = 0; t < 5; t++) {
for (var i = tree.length-1; i >= 0; i--) {
if (!tree[i].finished){
tree.push(tree[i].branchA());
tree.push(tree[i].branchB());
tree.push(tree[i].branchC());
}
tree[i].finished = true;
}
}
}
function draw() {
background(51);
x = mouseX;
y = mouseY;
for (var i = 0; i < tree.length; i++) {
tree[i].show();
tree[i].wind(x, y, tree[i].end.x, tree[i].end.y);
}
}
JS branch object:
function Branch(begin, end) {
this.begin = begin;
this.end = end;
this.finished = false;
this.origx = this.end.x;
this.origy = this.end.y;
this.show = function() {
stroke(255);
line(this.begin.x, this.begin.y, this.end.x, this.end.y);
}
this.branchA = function() {
var dir = p5.Vector.sub(this.end, this.begin);
dir.rotate(19.2);
dir.mult(0.67);
var newEnd = p5.Vector.add(this.end, dir);
var v = new Branch(this.end, newEnd);
return v;
}
this.branchB = function() {
var dir = p5.Vector.sub(this.end, this.begin);
dir.rotate(0);
dir.mult(0.67);
var newEnd = p5.Vector.add(this.end, dir);
var v = new Branch(this.end, newEnd);
return v;
}
this.branchC = function() {
var dir = p5.Vector.sub(this.end, this.begin);
dir.rotate(-19.2);
dir.mult(0.67);
var newEnd = p5.Vector.add(this.end, dir);
var v = new Branch(this.end, newEnd);
return v;
}
this.wind = function(mox,moy,treex,treey) {
var d = dist(mox,moy,treex,treey);
if (d < 20) {
this.end.x += random(-0.3, 0.3);
this.end.y += random(-0.3, 0.3);
}else{
this.end.x = this.origx;
this.end.y = this.origy;
}
}
}
P5 libraries : https://p5js.org/download/
From the docs:
https://github.com/processing/p5.js/wiki/Positioning-your-canvas
// sketch.js
function setup() {
var canvas = createCanvas(100, 100);
// Move the canvas so it's inside our <div id="sketch-holder">.
canvas.parent('sketch-holder');
background(255, 0, 200);
}
Create one instance of canvas with P5, then assigns its parent by dom id.

rotating SVG rect around its center using vanilla JavaScript

This is not a duplicate of the other question.
I found this talking about rotation about the center using XML, tried to implement the same using vanilla JavaScript like rotate(45, 60, 60) but did not work with me.
The approach worked with me is the one in the snippet below, but found the rect not rotating exactly around its center, and it is moving little bit, the rect should start rotating upon the first click, and should stop at the second click, which is going fine with me.
Any idea, why the item is moving, and how can I fix it.
var NS="http://www.w3.org/2000/svg";
var SVG=function(el){
return document.createElementNS(NS,el);
}
var svg = SVG("svg");
svg.width='100%';
svg.height='100%';
document.body.appendChild(svg);
class myRect {
constructor(x,y,h,w,fill) {
this.SVGObj= SVG('rect'); // document.createElementNS(NS,"rect");
self = this.SVGObj;
self.x.baseVal.value=x;
self.y.baseVal.value=y;
self.width.baseVal.value=w;
self.height.baseVal.value=h;
self.style.fill=fill;
self.onclick="click(evt)";
self.addEventListener("click",this,false);
}
}
Object.defineProperty(myRect.prototype, "node", {
get: function(){ return this.SVGObj;}
});
Object.defineProperty(myRect.prototype, "CenterPoint", {
get: function(){
var self = this.SVGObj;
self.bbox = self.getBoundingClientRect(); // returned only after the item is drawn
self.Pc = {
x: self.bbox.left + self.bbox.width/2,
y: self.bbox.top + self.bbox.height/2
};
return self.Pc;
}
});
myRect.prototype.handleEvent= function(evt){
self = evt.target; // this returns the `rect` element
this.cntr = this.CenterPoint; // backup the origional center point Pc
this.r =5;
switch (evt.type){
case "click":
if (typeof self.moving == 'undefined' || self.moving == false) self.moving = true;
else self.moving = false;
if(self.moving == true){
self.move = setInterval(()=>this.animate(),100);
}
else{
clearInterval(self.move);
}
break;
default:
break;
}
}
myRect.prototype.step = function(x,y) {
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(x,y));
}
myRect.prototype.rotate = function(r) {
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().rotate(r));
}
myRect.prototype.animate = function() {
self = this.SVGObj;
self.transform.baseVal.appendItem(this.step(this.cntr.x,this.cntr.y));
self.transform.baseVal.appendItem(this.rotate(this.r));
self.transform.baseVal.appendItem(this.step(-this.cntr.x,-this.cntr.y));
};
for (var i = 0; i < 10; i++) {
var x = Math.random() * 100,
y = Math.random() * 300;
var r= new myRect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16));
svg.appendChild(r.node);
}
UPDATE
I found the issue to be calculating the center point of the rect using the self.getBoundingClientRect() there is always 4px extra in each side, which means 8px extra in the width and 8px extra in the height, as well as both x and y are shifted by 4 px, I found this talking about the same, but neither setting self.setAttribute("display", "block"); or self.style.display = "block"; worked with me.
So, now I've one of 2 options, either:
Find a solution of the extra 4px in each side (i.e. 4px shifting of both x and y, and total 8px extra in both width and height),
or calculating the mid-point using:
self.Pc = {
x: self.x.baseVal.value + self.width.baseVal.value/2,
y: self.y.baseVal.value + self.height.baseVal.value/2
};
The second option (the other way of calculating the mid-point worked fine with me, as it is rect but if other shape is used, it is not the same way, I'll look for universal way to find the mid-point whatever the object is, i.e. looking for the first option, which is solving the self.getBoundingClientRect() issue.
Here we go…
FIDDLE
Some code for documentation here:
let SVG = ((root) => {
let ns = root.getAttribute('xmlns');
return {
e (tag) {
return document.createElementNS(ns, tag);
},
add (e) {
return root.appendChild(e)
},
matrix () {
return root.createSVGMatrix();
},
transform () {
return root.createSVGTransformFromMatrix(this.matrix());
}
}
})(document.querySelector('svg.stage'));
class Rectangle {
constructor (x,y,w,h) {
this.node = SVG.add(SVG.e('rect'));
this.node.x.baseVal.value = x;
this.node.y.baseVal.value = y;
this.node.width.baseVal.value = w;
this.node.height.baseVal.value = h;
this.node.transform.baseVal.initialize(SVG.transform());
}
rotate (gamma, x, y) {
let t = this.node.transform.baseVal.getItem(0),
m1 = SVG.matrix().translate(-x, -y),
m2 = SVG.matrix().rotate(gamma),
m3 = SVG.matrix().translate(x, y),
mtr = t.matrix.multiply(m3).multiply(m2).multiply(m1);
this.node.transform.baseVal.getItem(0).setMatrix(mtr);
}
}
Thanks #Philipp,
Solving catching the SVG center can be done, by either of the following ways:
Using .getBoundingClientRect() and adjusting the dimentions considering 4px are extra in each side, so the resulted numbers to be adjusted as:
BoxC = self.getBoundingClientRect();
Pc = {
x: (BoxC.left - 4) + (BoxC.width - 8)/2,
y: (BoxC.top - 4) + (BoxC.height - 8)/2
};
or by:
Catching the .(x/y).baseVal.value as:
Pc = {
x: self.x.baseVal.value + self.width.baseVal.value/2,
y: self.y.baseVal.value + self.height.baseVal.value/2
};
Below a full running code:
let ns="http://www.w3.org/2000/svg";
var root = document.createElementNS(ns, "svg");
root.style.width='100%';
root.style.height='100%';
root.style.backgroundColor = 'green';
document.body.appendChild(root);
//let SVG = function() {}; // let SVG = new Object(); //let SVG = {};
class SVG {};
SVG.matrix = (()=> { return root.createSVGMatrix(); });
SVG.transform = (()=> { return root.createSVGTransformFromMatrix(SVG.matrix()); });
SVG.translate = ((x,y)=> { return SVG.matrix().translate(x,y) });
SVG.rotate = ((r)=> { return SVG.matrix().rotate(r); });
class Rectangle {
constructor (x,y,w,h,fill) {
this.node = document.createElementNS(ns, 'rect');
self = this.node;
self.x.baseVal.value = x;
self.y.baseVal.value = y;
self.width.baseVal.value = w;
self.height.baseVal.value = h;
self.style.fill=fill;
self.transform.baseVal.initialize(SVG.transform()); // to generate transform list
this.transform = self.transform.baseVal.getItem(0), // to be able to read the matrix
this.node.addEventListener("click",this,false);
}
}
Object.defineProperty(Rectangle.prototype, "draw", {
get: function(){ return this.node;}
});
Object.defineProperty(Rectangle.prototype, "CenterPoint", {
get: function(){
var self = this.node;
self.bbox = self.getBoundingClientRect(); // There is 4px shift in each side
self.bboxC = {
x: (self.bbox.left - 4) + (self.bbox.width - 8)/2,
y: (self.bbox.top - 4) + (self.bbox.height - 8)/2
};
// another option is:
self.Pc = {
x: self.x.baseVal.value + self.width.baseVal.value/2,
y: self.y.baseVal.value + self.height.baseVal.value/2
};
return self.bboxC;
// return self.Pc; // will give same output of bboxC
}
});
Rectangle.prototype.animate = function () {
let move01 = SVG.translate(this.CenterPoint.x,this.CenterPoint.y),
move02 = SVG.rotate(10),
move03 = SVG.translate(-this.CenterPoint.x,-this.CenterPoint.y);
movement = this.transform.matrix.multiply(move01).multiply(move02).multiply(move03);
this.transform.setMatrix(movement);
}
Rectangle.prototype.handleEvent= function(evt){
self = evt.target; // this returns the `rect` element
switch (evt.type){
case "click":
if (typeof self.moving == 'undefined' || self.moving == false) self.moving = true;
else self.moving = false;
if(self.moving == true){
self.move = setInterval(()=>this.animate(),100);
}
else{
clearInterval(self.move);
}
break;
default:
break;
}
}
for (var i = 0; i < 10; i++) {
var x = Math.random() * 100,
y = Math.random() * 300;
var r= new Rectangle(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16));
root.appendChild(r.draw);
}

My javascript canvas map script and poor performance

Basically below is my script for a prototype which uses 128x128 tiles to draw a map on a canvas which user can drag to move around.
Script does work. However I have a few problems to be solved:
1. Poor performance and I can't figure out why.
2. I am missing a method to buffer the tiles before the actual drawing.
3. If you notice any other issues also that could help me to make things run more smoothly it would be fantastic.
Some explanations for the script:
variables
coordinates - Defines the actual images to be displayed. Image file names are type of '0_1.jpg', where 0 is Y and 1 is X.
mouse_position - As name says, is keeping record of mouse position.
position - This is a poorly named variable. It defines the position of the context drawn on canvas. This changes when user drags the view.
Any assistance would be appreciated greatly. Thank you.
var coordinates = [0, 0];
var mouse_position = [0, 0];
var position = [-128, -128];
var canvas = document.getElementById('map_canvas');
var context = canvas.getContext('2d');
var buffer = [];
var buffer_x = Math.floor(window.innerWidth/128)+4;
var buffer_y = Math.floor(window.innerHeight/128)+4;
var animation_frame_request = function() {
var a = window.requestAnimationFrame;
var b = window.webkitRequestAnimationFrame;
var c = window.mozRequestAnimationFrame;
var d = function(callback) {
window.setTimeout(callback, 1000/60);
}
return a || b || c || d;
}
var resizeCanvas = function() {
window.canvas.width = window.innerWidth;
window.canvas.height = window.innerHeight;
window.buffer_x = Math.floor(window.innerWidth/128)+4;
window.buffer_y = Math.floor(window.innerHeight/128)+4;
window.buffer = [];
for (row = 0; row < window.buffer_y; row++) {
x = [];
for (col = 0; col < window.buffer_x; col++) {
x.push(new Image());
}
window.buffer.push(x);
}
}
var render = function() {
animation_frame_request(render);
for (row = 0; row < window.buffer_y; row++) {
for (col = 0; col < window.buffer_x; col++) {
cy = window.coordinates[1]+row;
cx = window.coordinates[0]+col;
window.buffer[row][col].src = 'map/'+cy+'_'+cx+'.jpg';
}
}
for (row = 0; row < window.buffer_y; row++) {
for (col = 0; col < window.buffer_x; col++) {
window.context.drawImage(window.buffer[row][col],
window.position[0]+col*128,
window.position[1]+row*128, 128, 128);
}
}
}
var events = function() {
window.canvas.onmousemove = function(e) {
if (e['buttons'] == 1) {
window.position[0] += (e.clientX-window.mouse_position[0]);
window.position[1] += (e.clientY-window.mouse_position[1]);
if (window.position[0] >= 0) {
window.position[0] = -128;
window.coordinates[0] -= 1;
} else if (window.position[0] < -128) {
window.position[0] = 0;
window.coordinates[0] += 1;
}
if (window.position[1] >= 0) {
window.position[1] = -128;
window.coordinates[1] -= 1;
} else if (window.position[1] < -128) {
window.position[1] = 0;
window.coordinates[1] += 1;
}
render();
}
window.mouse_position[0] = e.clientX;
window.mouse_position[1] = e.clientY;
}
}
window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('load', resizeCanvas, false);
window.addEventListener('mousemove', events, false);
resizeCanvas();
To get better performance you should avoid changing the src of img nodes and move them around instead.
A simple way to minimize the number of img nodes handled and modified (except for screen positioning) is to use an LRU (Least Recently Used) cache.
Basically you keep a cache of last say 100 image nodes (they must be enough to cover at least one screen) by using a dictionary mapping the src url to a node object and also keeping them all in a doubly-linked list.
When a tile is required you first check in the cache, and if it's already there just move it to the front of LRU list and move the img coordinates, otherwise create a new node and set the source or, if you already hit the cache limit, reuse the last node in the doubly-linked list instead. In code:
function setTile(x, y, src) {
var t = cache[src];
if (!t) {
if (cache_count == MAXCACHE) {
t = lru_last;
t.prev.next = null;
lru_last = t.prev;
t.prev = t.next = null;
delete cache[t.src]
t.src = src;
t.img.src = src;
cache[t.src] = t;
} else {
t = { prev: null,
next: null,
img: document.createElement("img") };
t.src = src;
t.img.src = src;
t.img.className = "tile";
scr.appendChild(t.img);
cache[t.src] = t;
cache_count += 1;
}
} else {
if (t.prev) t.prev.next = t.next; else lru_first = t.next;
if (t.next) t.next.prev = t.prev; else lru_last = t.prev;
}
t.prev = null; t.next = lru_first;
if (t.next) t.next.prev = t; else lru_last = t;
lru_first = t;
t.img.style.left = x + "px";
t.img.style.top = y + "px";
scr.appendChild(t.img);
}
I'm also always appending the requested tile to the container so that it goes in front of all other existing tiles; this way I don't need to remove old tiles and they're simply left behind.
To update the screen I just iterate over all the tiles I need and request them:
function setView(x0, y0) {
var w = scr.offsetWidth;
var h = scr.offsetHeight;
var iy0 = y0 >> 7;
var ix0 = x0 >> 7;
for (var y=iy0; y*128 < y0+h; y++) {
for (var x=ix0; x*128 < x0+w; x++) {
setTile(x*128-x0, y*128-y0, "tile_" + y + "_" + x + ".jpg");
}
}
}
most of the time the setTile request will just update the x and y coordinates of an existing img tag, without changing anything else. At the same time no more than MAXCACHE image nodes will be present on the screen.
You can see a full working example in
http://raksy.dyndns.org/tiles/tiles.html

What is the most efficient way for me to set up this function in javascript?

Total noob here, i'm assuming there's a way to write this faster/smaller. Any advice?
Sorry if its not really reduced down & out of the framework i'm using, but here's a live example if that helps.
Live Example: http://linkthegeek.com/public/code/bookmarker/index.html
(only works in webkit, & I've only tested in chrome)
BannerOne = 1;
BannerTwo = 2;
BannerThree = 3;
BannerFour = 4;
BannerFive = 5;
PSD['bannerdrop-'+ BannerOne].y= -200;
PSD['bannerdrop-'+ BannerTwo].y= -200;
PSD['bannerdrop-'+ BannerThree].y= -200;
PSD['bannerdrop-'+ BannerFour].y= -200;
PSD['bannerdrop-'+ BannerFive].y= -200;
PSD['bannerbtn-'+ BannerOne].on("click", function(){Bookmark(BannerOne) });
PSD['bannerdrop-'+ BannerOne].on("click", function(){Bookmark(BannerOne) });
PSD['bannerbtn-'+ BannerTwo].on("click", function(){Bookmark(BannerTwo) });
PSD['bannerdrop-'+ BannerTwo].on("click", function(){Bookmark(BannerTwo) });
PSD['bannerbtn-'+ BannerThree].on("click", function(){Bookmark(BannerThree) });
PSD['bannerdrop-'+ BannerThree].on("click", function(){Bookmark(BannerThree) });
PSD['bannerbtn-'+ BannerFour].on("click", function(){Bookmark(BannerFour) });
PSD['bannerdrop-'+ BannerFour].on("click", function(){Bookmark(BannerFour) });
PSD['bannerbtn-'+ BannerFive].on("click", function(){Bookmark(BannerFive) });
PSD['bannerdrop-'+ BannerFive].on("click", function(){Bookmark(BannerFive) });
function Bookmark (viewnum) {
item = PSD['item-'+ viewnum ]
bannerbtn = PSD['bannerbtn-'+ viewnum ]
bannerdrop = PSD['bannerdrop-'+ viewnum ]
var down;
var away;
var small;
if (bannerbtn.opacity == 1) {
away = 0;
small = .03;
down = -13;
};
if (bannerbtn.opacity == 0) {
away = 1;
small = 1;
down = -200;
};
//animations
bannerdrop.animate({
properties:{y:down},
curve:"spring(100,15,200)"
});
bannerbtn.animate({
properties:{opacity:away, scale:small},
curve:"linear",
time:100
});
};
Don't quite understand your application here, but here's something that might set you in the right direction.
This is definitely not functional as I don't have a lot of the background information and have made assumptions:
var BannerCount = 5;
var PSD = [];
for (i = 0; i < count; i++) {
PSD[i] = {};
PSD[i].btn = document.getElementById('bannerbtn-' + i);
PSD[i].btn.on("click", function (eevent) {
Bookmark(eevent.srcElement);
});
PSD[i].y = -200;
PSD[i].on("click", function (eevent) {
Bookmark(eevent.srcElement);
});
PSD[i].drop = document.getElementById('bannerdrop-' + i).addEventListener("click",
function (eevent) {
Bookmark(eevent.srcElement);
});
}
function Bookmark(itemPSD) {
var down;
var away;
var small;
if (itemPSD.btn.style.opacity == 1) {
away = 0;
small = 0.03;
down = -13;
} else if (itemPSD.btn.style.opacity === 0) {
away = 1;
small = 1;
down = -200;
}
//animations
itemPSD.drop.animate({
properties: {
y: down
},
curve: "spring(100,15,200)"
});
itemPSD.btn.animate({
properties: {
opacity: away,
scale: small
},
curve: "linear",
time: 100
});
}
We may be need an object bannerdrop will save any attribute you have. So what we do is declare array of this object like:
function bannerdrop(y){
this.y = y;
this.on('click', function(){bookmark(this);});
}
function bookmark(obj){
var down;
var away;
var small;
//animations
obj.animate({
properties:{y:down},
curve:"spring(100,15,200)"
});
}
var bannerArray = new Array(new bannerdrop(-200), new bannerdrop(-200), new bannerdrop(-200));

Categories

Resources