I am using Raphael JS to creating a ERD like tool, but don't know to to create a table like instance by using Raphael.
paper = new Raphael(0,0,500,500);
var x = 100;
var y = 50;
var height = 50
var width = 100;
WriteTableRow(x,y,width*2,height,paper,"TOP Title");
y= y+height;
WriteTableRow(x,y,width,height,paper,"Score,Player");
y= y+height;
for (i=1;i<=4;i++)
{
var k;
k = Math.floor(Math.random() * (10 + 1 - 5) + 5);
WriteTableRow(x,y,width,height,paper,i+","+ k + "");
y= y+height;
}
function WriteTableRow(x,y,width,height,paper,TDdata)
{
var TD = TDdata.split(",");
for (j=0;j<TD.length;j++)
{
var rect = paper.rect(x,y,width,height).attr({"fill":"white","stroke":"red"});
paper.text(x+width/2, y+height/2, TD[j])
x = x + width;
}
}
//http://jsfiddle.net/LG5zn/116/
Raphael can draw anything, but if you're doing a lot of manual creation of tables and so forth than you're probably fighting the framework. My favorite aspect of the library is that is works so seamlessly with traditional HTML, CSS and Javascript. I would strong suggest taking what you want from HCJ and using Raphael for whatever that can't easily do.
Related
I'm learning on my own JavaScript so I'm doing something like a website using p5.js
The thing is that a div holding my canvas for p5.js and I want it to be responsive. In this canvas, I do have an object that needs the div width and height to be constructed.
Problem is that I don't know how to get this information. I tried jQuery but I don't know how to extract value out of a jQuery function and I'm don't know if it's an excessive way to do it.
//--------------------------constant--------------------------------------------
//Canvas
const DROPNUMBER = 1500;
//--------------------------classe---------------------------------------------
function Drop(width, heigth) {
//declaring and setting drop's attribute
this.spawn = function(width) {
//size and position
this.x = Math.random() * -width*1.5;
this.y = Math.random() * heigth;
this.size = Math.random() * 20 ;
//color
this.colorR = 138 + Math.random() * 50;
this.colorV = 43 + Math.random() * 50;
this.colorB = 226 + Math.random() * 50;
this.colorA = Math.random() * 127 +50;
//speed and landing
this.speed = Math.random();
this.hasLanded = false;
}
//call func to set the attribute
this.spawn(width);
//make the drop falls
this.fall = function() {
//if the drop can fall
if (this.x < width) {
this.x = this.x + this.speed;
this.speed = this.speed + 0.01;
//if the drop did land
if (this.y + this.size > width && this.hasLanded == false) {
this.hasLanded = true;
}
}
//if the drop did fall
else {
this.spawn(width);
}
}
//display the drop
this.display = function() {
noStroke();
//Some kind of purple color
fill(this.colorR, this.colorV, this.colorB, this.colorA);
rect(this.x, this.y, this.size, this.size)
}
}
//--------------------------setup---------------------------------------------
function setup() {
clientHeight = document.getElementById('header').clientHeight;
clientWidth = document.getElementById('header').clientWidth;
canvas = createCanvas(clientWidth, clientHeight);
canvas.parent('sketch-holder');
window.canvas = canvas;
}
//-------------------------Variable---------------------------------------------
var n = DROPNUMBER;
var drops = new Array();
//creating an array of drop for the rain
for (let i = 0; i < n; i++) {
//800 800 is height and the width that i want to change !
drops.push(new Drop(800,800));
}
//--------------------------draw------------------------------------------------
function draw() {
background(48, 64, 96);
//each drop
for (let i = 0; i < n; i++) {
//Make them falling
drops[i].fall();
//display the result
drops[i].display();
}
}
The code is just showing that drops ( the object that needs height and width) are being constructed out of draw or setup function.
I did search already on Stack Overflow to this kind of problem too.
use a regular DOM js it's worked:
let b = document.getElementById("parentElement");
let w = b.clientWidth;
let h = b.clientHeight;
console.log(w, h);
You don't need to use JQuery for this. Take a look at the P5.dom library that provides a bunch of functionality for manipulating HTML elements in P5.js.
I'm not sure exactly what you're trying to do, but here's a simple example. If we have a div on the page with and ID of myId, then to get its width we could use P5.dom to do this:
var myDiv = select('myId');
var myWidth = myDiv.style.width;
console.log('width: ' + myWidth);
To get the width of an element in JavaScript, you can select that element using document.querySelector(). Any CSS selector is a valid first argument to that function. E.g. the following will select the <body> tag:
document.querySelector('body')
Once you have an element selected, you can get it's width by accessing the clientWidth property. E.g. the following tells you the width of the <body> tag:
document.querySelector('body').clientWidth
So just replace body with a CSS selector for the element you want to select.
I am trying to generate 5 images on the left-hand side of the page in random positions. The images are displayed in a row across the top and not in the random positions that I require. I do have img{position:absolute} within my CSS. I am sorry if this has been covered previously, I have searched endlessly for an answer and tried many different examples, but I am still stuck, can someone point me in the right direction, please.
<script>
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
function getRandom(x, y) {
return Math.floor(Math.random() * (y - x)) + x + 'px';
};
function generateFaces() {
for (var i=0; i<numberOfFaces; i++) {
var faces = document.createElement("img");
faces.src = "smile.png";
faces.style.top = getRandom(0, 400);
faces.style.left = getRandom(0, 400);
leftSide.appendChild(faces);
};
};
</script>
http://jsfiddle.net/pynaam1f/
OR
http://jsfiddle.net/pynaam1f/1/
img{
position:absolute;
}
I am generating 5 circles with a for loop in a canvas and I want to give them a class so I can control them with jquery, but I am doing something wrong. Can you guys figure out what's happening?
var stage;
var quantity = 6,
width = 60,
height = 60,
circles = [];
function init(){
stage = new createjs.Stage("myCanvas");
stage.width = 500;
stage.height = 600;
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener("tick", onTick);
setupGame();
}
function setupGame() {
for(var i = 0; i < quantity; i++) {
var circle = document.createElement("img");
circle.setAttribute('src', 'images/circles/circle'+i+'.png');
circle.className = "circle";
circle.style.position = "absolute";
circle.style.left = Math.floor((Math.random() * 100)) + "%";
circle.style.top = Math.floor((Math.random() * 100)) + "%";
circle.style.width = width + "px";
circle.style.height = height + "px";
document.body.appendChild(circle);
circles.push(circle);
}
}
function onTick(e){
stage.update(e);
}
NEW VERSION. With the help from JonnyD, I now have a functional loop. The only problem is that the images get appended to the body, and not to my stage. I have tried stage.appendChild(circle), but it's not working.
Here is a link to an online source so you guys can check it out = LINK
A lot is wrong with your code.
You are trying to add properties to strings within an array which is not possible. Properties are added to objects using dot or bracket notation..
Dot notation
foo.bar.baz
Square bracket notation
foo['bar']['baz']
What I think you want to do is create five circles on the 'screen' or more technically correct DOM (https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) at random positions with set H&W of 60px with classnames of myClass..
I have rewritten your code for you, you can remove the style javascript lines and add them in the CSS if you wish.. All you were really doing wrong was attempting to add properties to array values, wrong technique for the code and missing off .style before width, height. Note You add className's and width and height attributes to DOM elements only.
You can now access the individual circles through a for loop and the circles array or by using the nth-child selector with CSS. e.g .circle:nth-child(1) {animation/transition}
var quantity = 5,
width = 60,
height = 60
circles = [];
function setUp() {
for(var i = 0; i < quantity; i++) {
var circle = document.createElement("div");
circle.className = "circle";
circle.style.position = "absolute";
circle.style.left = Math.floor((Math.random() * 100)) + "%";
circle.style.top = Math.floor((Math.random() * 100)) + "%";
circle.style.backgroundColor = "black";
circle.style.width = width + "px";
circle.style.height = height + "px";
circles.push(circle);
document.body.appendChild(circle);
}
}
setUp();
.circle {
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
}
I didn't see you were using CreateJS.. in that case using the notation like so is okay..
var circle = new createjs.Shape();
circle.graphics.beginFill("DeepSkyBlue").drawCircle(0, 0, 50);
circle.x = 100;
circle.y = 100;
stage.addChild(circle);
ensure that you update the stage as well.
stage.update();
I realize this question has been answered, but since I clicked on this for trying to find out how to add a class to a canvas object in jquery, I'll post how to do that.
var thing = canvas_object;
$('body').append(thing);
var canvas = $('canvas');
canvas.addClass('test');
Things inside canvas are not in DOM, but elements in Scalable Vector Graphics images are, and can be manipulated this way.
Try using SVG if convenient. svg.js is a lightweight library to manipulate SVG.
I have a 3D matrix of size (X, Y, Z) which is stored in a data structure as Z matrices, each X x Y in size. I would like to re-slice these matrices to obtain X slices, each Y x Z in size. In other words, I want to reslice a 3D matrix stored as XY slices in the YZ plane. The use case is to reslice axial CT images into sagittal images. I am working inside a browser environment.
Here's an example of what I am trying to achieve:
I have implemented the naive (iterative) solution in Python, which takes O(Y * Z) per slice. I haven't even bothered writing out the corresponding JavaScript implementation, because this approach is too slow by several orders of magnitude.
import glob
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import imread
height, width, depth = 512, 512, 100
volume = np.zeros((height, width, depth))
s = 0
for filename in glob.iglob('./*.jpg'):
volume[:,:,s] = imread(filename)[...,0]/255.0
s += 1
reslice = np.zeros((depth, height, width))
for s in xrange(0, width):
current = np.zeros((depth, height))
for i in xrange(0, height):
for j in xrange(0, depth):
current[j,i] = volume[i,s,j]
reslice[:,:,s] = current
This algorithm seems to be amenable to parallelization. For example, in CUDA, one could load the 3D data into global memory, create one thread per pixel, then iterate for every slice in the new direction, and on each iteration ask the right pixels to fire in order to fill out the current slice. This would be a trivial kernel to write, and would be approximately O(1) per slice. However, I don't have access to CUDA in the browser.
Mapping from CUDA to WebCL is relatively straightforward, but WebCL is out of question given inexistent vendor support ATM. Therefore, I'm thinking WebGL is the ideal solution.
I'm not too sure how this would be done in the "WebGL" paradigm, but I'm sure it can be done, and I suspect it is fairly trivial as well. I can't seem to find where to start, however, and resources on doing general-purpose computations with OpenGL are extremely scarce. How would I go about using OpenGL to speed up reslicing of a 3D matrix inside the browser?
You don't have necessarily to use webGL to be fast enough.
If you use a 3D array, JavaScript might be too slow but by using a flat array the time to reslice is in fact similar to the time it takes to create the array!
Another trick is to use a typed array to reduce memory usage and improve performances (Uint8Array).
I created a small class to handle such a flat array and to slice it.
I think the most relevant thing you want is in fact to get a view, either on (x, y) axes or (y, z) axes.
Since Array creation is very slow, you want to build the view on place within a fixed buffer. And since you want also a sliced view, you have to create a buffer and method also for the sliced view.
It's fast: creating a view for your 512X512x100 example take less than 5 ms!
(So in fact, the putImageData you'll have to do afterward will quite take more time! )
Fiddle is here: http://jsfiddle.net/n38mwh95/1/
Here's the class handling the data, you'll have to change the constructor so it accepts the real raw data:
function Array3D(xSize, ySize, zSize) {
this.xSize = xSize;
this.ySize = ySize;
this.zSize = zSize;
var xyMultiplier = xSize * ySize;
this.array = new Uint8Array(xSize * ySize * zSize);
this.view = new Uint8Array(xSize * ySize);
this.slicedView = new Uint8Array(ySize * zSize);
this.valueAt = function (x, y, z) {
return this.array[x + xSize * (y + z * ySize)];
};
this.setValueAt = function (x, y, z, val) {
return this.array[x + xSize * (y + z * ySize)] = val;
};
this.buildView = function (z) {
var src = this.array;
var view = this.view;
for (var x = 0; x < xSize; x++) {
for (var y = 0; y < ySize; y++) {
view[x + xSize * y] = src[x + xSize * (y + z * ySize)];
}
}
return view;
};
this.buildSlicedView = function (x) {
var src = this.array;
var sView = this.slicedView;
for (var y = 0; y < ySize; y++) {
for (var z = 0; z < zSize; z++) {
sView[y + ySize * z] = src[x + xSize * (y + z * ySize)];
}
}
return sView;
};
}
In use:
var xSize = 512;
var ySize = 512;
var zSize = 100;
var t1, t2;
t1 = performance.now();
var testArray = new Array3D(xSize, ySize, zSize);
t2 = performance.now();
console.log('created in :' + (t2 - t1));
t1 = performance.now();
var resliced = testArray.buildView(10);
t2 = performance.now();
console.log('building view in :' + (t2 - t1));
var x = 80;
t1 = performance.now();
var resliced = testArray.buildSlicedView(x);
t2 = performance.now();
console.log('building sliced view in :' + (t2 - t1));
Results:
created in :33.92199998779688 (index):73
building view in :2.7559999871300533 (index):79
building sliced view in :5.726000003051013
At the end of the code I also added some code to render the view.
Don't forget to cache the canvas imageData: create it only once then re-use it for best performance.
You could easily have a real-time rendering in fact.
I'm implementing a javascript software renderer (for academic purposes). It handles representing a 3d object as triangles, and handles Perspective Projection from 3d space to 2d space.
Until now, I used the lineTo and fillRect to represent the vertices and the lines on screen. I've even used lineTo to do Scan Line triangle filling. (you can check out the project here)
So far the FPS has been quite good. But the last part of the assignment is to implement z-Buffering :P. To my knowledge, the only way to do this is to stop filling my triangles using lineTo and fill them with either an array of 1px lines or an array of 1px squares. (because before I draw each "pixel", I have to check the depth buffer and see if I should actually draw it or not.)
The problem is, filling triangles with tiny rectangles or lines is SLOW. Gets everything down to 2FPS. So my question is, is there any method to draw one pixel instead of a tiny line (which may be faster)?
Alternatively, what else can I do to speed things up? My goal is to have it spin fast enough to demo the principle. (6-10fps would be enough)
Cheers.
[EDIT] While I wait for an answer, I will procede to modify my triangle filling functions to draw 4px sized "pixels" instead of 1px. But that will look jaggedy...
Check this out: http://jsfiddle.net/ZXjAM/2/
// points 0,1,2,3 front face
var fAvgZ = (cube.processPoints[0].colorZ +
cube.processPoints[1].colorZ +
cube.processPoints[2].colorZ +
cube.processPoints[3].colorZ) / 4 / 20;
// points 0,2,4,6 top
var tAvgZ = (cube.processPoints[0].colorZ +
cube.processPoints[2].colorZ +
cube.processPoints[4].colorZ +
cube.processPoints[6].colorZ) / 4 / 20;
// points 4,5,6,7 rear
var reAvgZ = (cube.processPoints[4].colorZ +
cube.processPoints[5].colorZ +
cube.processPoints[6].colorZ +
cube.processPoints[7].colorZ) / 4 / 20;
// points 1,3,5,7 bottom
var bAvgZ = (cube.processPoints[1].colorZ +
cube.processPoints[3].colorZ +
cube.processPoints[5].colorZ +
cube.processPoints[7].colorZ) / 4 / 20;
// points 2,3,6,7 right side
var rAvgZ = (cube.processPoints[2].colorZ +
cube.processPoints[3].colorZ +
cube.processPoints[6].colorZ +
cube.processPoints[7].colorZ) / 4 / 20;
// points 0,1,4,5 left side
var lAvgZ = (cube.processPoints[0].colorZ +
cube.processPoints[1].colorZ +
cube.processPoints[4].colorZ +
cube.processPoints[5].colorZ) / 4 / 20;
var layers = [{key:0, val:fAvgZ},
{key:1, val:fAvgZ},
{key:2, val:tAvgZ},
{key:3, val:tAvgZ},
{key:4, val:reAvgZ},
{key:5, val:reAvgZ},
{key:6, val:bAvgZ},
{key:7, val:bAvgZ},
{key:8, val:rAvgZ},
{key:9, val:rAvgZ},
{key:10, val:lAvgZ},
{key:11, val:lAvgZ}];
var outLay = layers.sort(function(a,b){
return (a.val - b.val);
});
for(var i = 0; i < outLay.length; i++)
{
var k = outLay[i].key;
...
}
This is, by no means, the most efficient way to average/sort the point values, and it can probably be done with fewer lines of code using the cube's pre-existing properties, but the basic concept remains the same.
I'm finding the average z-index and using that to assume layering order. Obviously, this won't work for everything ever, but for simple polyhedra, it should suffice.
This can be simplified to:
var layers = [];
for (var i = 0; i < cube.sides.length; i++){
var side = cube.sides[i];
var avg = (cube.processPoints[side.a].colorZ +
cube.processPoints[side.b].colorZ +
cube.processPoints[side.c].colorZ) / 3 / 20;
layers.push({key:i, val:avg});
}
var outLay = layers.sort(function(a,b){
return (a.val - b.val);
});
There do seem to be some fringe-cases where there is a quick ordering-problem.
This seems to be more accurate: http://jsfiddle.net/ZXjAM/4/
var layers = [];
for (var i = 0; i < 12; ++i){
var side1 = cube.sides[i];
var side2 = cube.sides[++i];
var avg = (cube.processPoints[side1.a].colorZ +
cube.processPoints[side1.b].colorZ +
cube.processPoints[side1.c].colorZ +
cube.processPoints[side2.a].colorZ +
cube.processPoints[side2.b].colorZ +
cube.processPoints[side2.c].colorZ) / 6;
layers.push({key:i-1, val:avg});
layers.push({key:i, val:avg});
}
var outLay = layers.sort(function(a,b){
return (a.val - b.val);
});