when i create dynamically svg text circle is working fine in number.but i am using small letter (example:- ffffffiiiisasdasdas) text circle create half but i need full circle and Shape should be react according to content which we are placing ..
please check image following
1.http://tinypic.com/view.php?pic=15fll6b&s=8
2.http://tinypic.com/view.php?pic=fe1181&s=8
following code use
<svg width="845" height="350" viewBox="0 0 845 350" clip-rule="nonzero" >
<g
data-ng-attr-fill="{{addText.color}}"
data-ng-attr-width="{{addText.w}}"
data-ng-attr-height="{{addText.h}}"
data-ng-attr-transform="{{rotate(addText)}}"
strok <defs>
<path stroke-width = "3"
fill="userSpaceOnUse"
data-ng-attr-id="temp-{{addText.id}}"
data-ng-attr-d="{{makeBox1(addText, true)}}" />
</defs>
<text ng-if="addText.text" glyph-orientation-vertical="90" lengthAdjust="spacingAndGlyphs" "
data-ng-attr-text-anchor="{{addText.text.anchor}}"
data-ng-attr-font-family="{{addText.text.font}}"
data-ng-attr-font-style="{{addText.text.italic ? 'italic' : 'none'}}"
data-ng-attr-font-weight="{{addText.text.bold ? 'bold' : 'normal'}}"
data-ng-attr-font-size="{{addText.text.size}}"
data-ng-attr-x="{{arcMid(addText)}}"
letter-spacing="2";
style="text-align:justify"
kerning="8">
<textPath data-ng-xlink-href="#temp-{{addText.id}}" method = "stretch"
writing-mode="lr-tb" clip-rule="nonzero" xlink:href="">
{{addText.text.text}}</textPath>
</text>
<path fill="none" stroke="#EEE" data-ng-attr-d="{{makeBox1(addText,true)}}" />
</g>
</svg>
javascript
$scope.makeBox1 = function makeBox1(item, temp) {
if (item.c == 1) {
var ma = $('#txtsearch').val();
var legth = ma.length;
console.log(legth + "m");
if (item.r == 0) {
item.r = item.h / 2;
}
var x1 = item.x + item.w / 2,
y1 = item.y + (item.h),
x2 = x1 + 1,
r = item.r;
if (temp) {
x1 = 270 + item.w / 2;
y1 = 30 + (item.h);
x2 = x1 + 1;
}
item.r = ((((((legth) * item.text.size * 5) / (legth / 0.9))) * legth * .02) + (legth * 0.09));
if (item.r > 137) {
item.r = 137;
}
x1 = 424.5;
y1 = 293;
r = item.r;
x2 = 425.5;
var y2 = 293
return "M " + x1 + " " + y1 + " " +
"A " + r + " " + r + " 0 1 1 " + x2 + " " + y2;
}
}
It's working for numbers because they always have a fixed width - or almost always. That is because you typically want numbers to align in columns - in invoices for instance.
Your complicated equation for calculating the circle radius is based on the font size. The formula has obviously been tweaked so it works well with the width of numerals in the font you are using. But it won't work with general non-numeric text. Or probably with numerals in a different font.
It is going to be hard to get this to work perfectly in every case, because different browsers may implement their <textPath> elements differently.
The best you can do is to measure the text length, and then calculate the radius from that, by dividing by (2*PI).
You can get the length of the text in a <text> element by calling getComputedTextLength() on the element.
var msg="ffffffiiiisasdasdas";
// Get SVG
var mysvg = document.getElementById("mysvg");
// Get text length
var tmp = document.createElementNS("http://www.w3.org/2000/svg", "text");
tmp.textContent = msg;
mysvg.appendChild(tmp);
var len = tmp.getComputedTextLength();
mysvg.removeChild(tmp);
//alert("len = "+len);
// Make the circle path for the msg to sit on
var x1 = 424.5,
y1 = 293,
x2 = 425.5,
y2 = 293;
var r = len / (2 * Math.PI);
var circ = document.createElementNS("http://www.w3.org/2000/svg", "path");
circ.setAttribute("id", "circ");
circ.setAttribute("d", "M " + x1 + " " + y1 + " " +
"A " + r + " " + r + " 0 1 1 " + x2 + " " + y2);
mysvg.appendChild(circ);
// Make the textPath element
var tp1 = document.createElementNS("http://www.w3.org/2000/svg", "text");
mysvg.appendChild(tp1);
var tp2= document.createElementNS("http://www.w3.org/2000/svg", "textPath");
tp2.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#circ");
tp2.textContent = msg;
tp1.appendChild(tp2);
svg text {
font-family: sans-serif;
font-size: 20px;
}
#circ {
fill: none;
stroke: black;
}
<svg id="mysvg" width="845" height="350" viewBox="0 0 845 350">
</svg>
Related
I have a svg path with a textPath connecting 2 divs from center like this:
item1.style.top="20px";
item1.style.left="20px";
item2.style.top="40px";
item2.style.left="160px";
var x1=parseFloat(item1.style.left)+ item1.offsetWidth / 2;
var y1=parseFloat(item1.style.top) + item1.offsetHeight / 2;
var x2=parseFloat(item2.style.left) + item2.offsetWidth / 2;
var y2=parseFloat(item2.style.top) + item2.offsetHeight / 2;
path1.setAttribute("d",`M ${x1} ${y1} L ${x2} ${y2}`)
*{
margin:0;
}
div{
height:2rem;
width:2rem;
position:absolute;
background-color:black;
box-sizing:border-box;
}
<div id="item1"></div>
<div id="item2" style="width:10rem; height:3rem"></div>
<svg id="svg1" style="overflow:visible">
<path id="path1" fill="none" stroke="red" stroke-width="3" />
<text font-size="24" dy="-10" text-anchor="middle">
<textPath href="#path1" fill="green" startOffset="50%">T</textPath>
</text>
</svg>
But as you can see the Text "T" isn't technically centered because of the height & width
so is there a way to shift the text (without changing the path d) into visual center?
like this:
Note
The height, width & position of the divs will change so a more flexible & versatile approach would be better
You could find the intersection points between the rectangles' borders and your textPath.
The final path start and end coordinates would be the calculated intersection points.
item1.style.top = "20px";
item1.style.left = "20px";
item2.style.top = "40px";
item2.style.left = "160px";
let svg = document.querySelector('svg');
let cx1 = parseFloat(item1.style.left) + item1.offsetWidth / 2;
let cy1 = parseFloat(item1.style.top) + item1.offsetHeight / 2;
let cx2 = parseFloat(item2.style.left) + item2.offsetWidth / 2;
let cy2 = parseFloat(item2.style.top) + item2.offsetHeight / 2;
// text path coordinates
let lTextP = [cx1, cy1, cx2, cy2];
renderLine(svg, lTextP)
// rect1: left, right, top, bottom
let x1 = parseFloat(item1.style.left);
let rx1 = x1 + item1.offsetWidth;
let y1 = parseFloat(item1.style.top);
let by1 = y1 + item1.offsetHeight;
// rect2: left, right, top, bottom
let x2 = parseFloat(item2.style.left);
let rx2 = x1 + item2.offsetWidth;
let y2 = parseFloat(item2.style.top);
let by2 = y2 + item2.offsetHeight;
// 1st rect: right border
let l1 = [rx1, y1, rx1, by1];
renderLine(svg, l1)
// 2nd rect: left border
let l2 = [x2, y2, x2, by2];
renderLine(svg, l2)
// find intersections between textpath and rect borders
let intersection1 = getVectorIntersection(l1, lTextP, true);
renderPoint(svg, intersection1, 'orange', '1%');
let intersection2 = getVectorIntersection(l2, lTextP, true);
renderPoint(svg, intersection2, 'orange', '1%');
// shorten text path according to intersections
[cx1, cy1] = intersection1;
[cx2, cy2] = intersection2;
path1.setAttribute("d", `M ${cx1} ${cy1} L ${cx2} ${cy2}`);
/**
* helper: get intersection coordinates
* based on
* source: https://dirask.com/posts/JavaScript-calculate-intersection-point-of-two-lines-for-given-4-points-VjvnAj
*/
function getVectorIntersection(l1, l2, exact = false, decimals = 3) {
let intersection = [];
let dx1 = l1[0] - l1[2];
let dy1 = l1[1] - l1[3];
let dx2 = l2[0] - l2[2];
let dy2 = l2[1] - l2[3];
// down part of intersection point formula
let d = dx1 * dy2 - dy1 * dx2;
if (d === 0) {
console.log('parallel')
return false;
} else {
// upper part of intersection point formula
let u1 = l1[0] * l1[3] - l1[1] * l1[2];
let u4 = l2[0] * l2[3] - l2[1] * l2[2];
// only exact intersections
let isIntersecting = u4 > d;
if (exact && !isIntersecting) {
return false;
}
// intersection point formula
let px = +((u1 * dx2 - dx1 * u4) / d).toFixed(decimals);
let py = +((u1 * dy2 - dy1 * u4) / d).toFixed(decimals);
intersection = [px, py];
}
return intersection;
}
// debug helper: render coordinates as markers
function renderPoint(svg, coords, fill = "red", r = "0.5%") {
if (coords.length) {
let marker =
'<circle cx="' +
coords[0] +
'" cy="' +
coords[1] +
'" r="' +
r +
'" fill="' +
fill +
'" ><title>' +
coords.join(", ") +
"</title></circle>";
svg.insertAdjacentHTML("beforeend", marker);
}
}
// debug helper: render lines
function renderLine(svg, coords, color = "purple", strokeWidth = 1) {
let [x1n, y1n, x2n, y2n] = coords;
let newLine =
'<line x1="' +
x1n +
'" y1="' +
y1n +
'" x2="' +
x2n +
'" y2="' +
y2n +
'" stroke-width="' + strokeWidth + '" stroke="' + color + '" />';
svg.insertAdjacentHTML("beforeend", newLine);
}
*{
margin:0;
}
.item{
height:2rem;
width:2rem;
position:absolute;
z-index:-1;
background-color:black;
box-sizing:border-box;
}
<div class="item" id="item1"></div>
<div class="item" id="item2" style="width:10rem; height:3rem"></div>
<svg id="svg1" style="overflow:visible">
<text font-size="24" dy="-10" text-anchor="middle">
<textPath href="#path1" fill="green" startOffset="50%">T</textPath>
</text>
<path id="path1" fill="none" stroke="red" stroke-width="3" stroke-linecap="square" />
</svg>
An easier alternative might be to draw the text path between the vertical centers like so:
var x1=parseFloat(item1.style.left)+ item1.offsetWidth ;
var y1=parseFloat(item1.style.top) + item1.offsetHeight / 2;
var x2=parseFloat(item2.style.left);
var y2=parseFloat(item2.style.top) + item2.offsetHeight / 2;
item1.style.top="20px";
item1.style.left="20px";
item2.style.top="40px";
item2.style.left="160px";
var x1=parseFloat(item1.style.left)+ item1.offsetWidth ;
var y1=parseFloat(item1.style.top) + item1.offsetHeight / 2;
var x2=parseFloat(item2.style.left);
var y2=parseFloat(item2.style.top) + item2.offsetHeight / 2;
path1.setAttribute("d",`M ${x1} ${y1} L ${x2} ${y2}`)
*{
margin:0;
}
.item{
height:2rem;
width:2rem;
position:absolute;
z-index:-1;
background-color:black;
box-sizing:border-box;
}
<div class="item" id="item1"></div>
<div class="item" id="item2" style="width:10rem; height:3rem"></div>
<svg id="svg1" style="overflow:visible">
<text font-size="24" dy="-10" text-anchor="middle">
<textPath href="#path1" fill="green" startOffset="50%">T</textPath>
</text>
<path id="path1" fill="none" stroke="red" stroke-width="3" stroke-linecap="square" />
</svg>
The solution provided by #herrstrietzel works but I found another solution
I used this solution and calculated the distance required to center and then used dx attribute to simply shift the text by that much
I'm attempting to generate a path around 2 circles that should follow them as I move them around. I've based this on an example that I found and built a prototype of what I'm expecting to achieve example
I've started including this in my application, but for some reason I can't seem to get the green path to draw around the correct positions, and I can't figure out why.
I've put together a code example to illustrate:
function generatePath(planet, moon, join) {
function distanceBetween(x1, y1, x2, y2) {
var a = (x2 - x1) * (x2 - x1);
var b = (y2 - y1) * (y2 - y1);
return Math.sqrt(a + b);
};
function circleYFromX(circle, x) {
return Math.sqrt(Math.pow(circle.r, 2) - Math.pow(x - circle.x, 2));
};
function calculateAngle(origin, point) {
var tan = (point.y - origin.y) / (point.x - origin.x);
var angle = Math.atan(tan) / Math.PI * 180 + 90;
if (point.x < origin.x) angle += 180;
return angle;
};
// Work out the distance between the moon and planet
var distance = distanceBetween(planet.x, planet.y, moon.x, moon.y);
var originDistance = planet.r - moon.r;
var distanceDiff = distance - originDistance;
if (distanceDiff < 1) {
distanceDiff = 1;
}
console.log(distance);
console.log(planet.r);
console.log(moon.r);
console.log(join.r);
console.log(planet.r + moon.r + 2 * join.r);
// Determine if the moon has moved out of the planet's gravitational pull
if (distance > 2 * join.r + planet.r + moon.r) {
return;
}
moon.h = 0;
moon.k = 0 - planet.r + moon.r - distanceDiff;
var triangleA = planet.r + join.r; // Side planet
var triangleB = moon.r + join.r; // Side moon
var triangleC = Math.abs(moon.k - 0); // Side c
var triangleP = (triangleA + triangleB + triangleC) / 2; // Triangle half perimeter
var triangleArea = Math.sqrt(triangleP * (triangleP - triangleA) * (triangleP - triangleB) * (triangleP - triangleC)); // Triangle area
var triangleH;
var triangleD;
if (triangleC >= triangleA) {
var triangleH = 2 * triangleArea / triangleC; // Triangle height
var triangleD = Math.sqrt(Math.pow(triangleA, 2) - Math.pow(triangleH, 2)); // Big circle bisection of triangleC
} else {
var triangleH = 2 * triangleArea / triangleA; // Triangle height
var triangleD = Math.sqrt(Math.pow(triangleC, 2) - Math.pow(triangleH, 2)); // Small circle bisection of triangleA
}
planet.tan = triangleH / triangleD;
planet.angle = Math.atan(planet.tan);
planet.sin = Math.sin(planet.angle);
planet.intersectX = planet.sin * planet.r;
planet.cos = Math.cos(planet.angle);
planet.intersectY = planet.cos * planet.r;
join.x = 0 + planet.sin * (planet.r + join.r);
join.y = 0 - planet.cos * (planet.r + join.r);
var coord1 = {
x: -planet.intersectX,
y: -planet.intersectY
};
var coord2 = {
x: planet.intersectX,
y: -planet.intersectY
}
moon.tan = (moon.k - join.y) / (moon.h - join.x);
moon.angle = Math.atan(moon.tan);
moon.intersectX = join.x - Math.cos(moon.angle) * (join.r);
moon.intersectY = join.y - Math.sin(moon.angle) * (join.r);
// If we have any bad values then just return no path
if (isNaN(coord1.x) || isNaN(coord1.y) || isNaN(coord2.x) || isNaN(coord2.y)) {
return;
}
var pathD = "M " + coord1.x + " " + coord1.y + " A " + planet.r + " " + planet.r + " 0 1 0 " + coord2.x + " " + coord2.y;
if (join.x - join.r <= 0 && moon.k < join.y) {
var crossOverY = circleYFromX(join, 0);
pathD += "A " + join.r + " " + join.r + " 0 0 1 0 " + (join.y + crossOverY);
pathD += "m 0 -" + (crossOverY * 2);
}
pathD += "A " + join.r + " " + join.r + " 0 0 1 " + moon.intersectX + " " + moon.intersectY;
var largeArcFlag = 1;
if (join.y < moon.k) {
largeArcFlag = 0;
}
pathD += "a " + moon.r + " " + moon.r + " 0 " + largeArcFlag + " 0 " + (moon.intersectX * -2) + " 0";
if (join.x - join.r <= 0 && moon.k < join.y) {
pathD += "A " + join.r + " " + join.r + " 0 0 1 0 " + (join.y - crossOverY);
pathD += "m 0 " + (crossOverY * 2);
}
pathD += "A " + join.r + " " + join.r + " 0 0 1 " + coord1.x + " " + coord1.y;
pathD += "A " + join.r + " " + join.r + " 0 0 1 " + coord1.x + " " + coord1.y;
return pathD;
};
var container = d3.select(".planet");
var moon = d3.select(".moon");
var tempPlanet = { x: -181.77581967381693, y: -144.9613789321555, r: 152 };
var tempMoon = { x: 0, y: 0, r: 32 };
var link = { r: 7.9 };
var pathD = generatePath(tempPlanet, tempMoon, { r: 31 });
if (pathD) {
moon.append("path")
.attr("d", pathD)
.attr("transform", "translate(" + [-181.77581967381693, 144.9613789321555] + ")")
.attr("class", "gravity")
.style("fill", "none")
.style("stroke", "red")
.style("stroke-linecap", "round")
.style("stroke-width", 2);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="1680" height="523">
<g width="1680" height="523">
<g class="galaxy-main" width="1680" height="523">
<g class="planet selected" transform="translate(341,300) scale(0.5,0.5)">
<circle r="150" style="fill: rgb(72, 119, 159); stroke-dasharray: 944.477796076938px; stroke-dashoffset: 0px; stroke-width: 8px; stroke: rgb(255, 255, 255);"></circle>
<g class="moon" transform="translate(181.77581967381693,-144.96137893215555)">
<circle r="30" class="moon-circle" id="3" style="fill: rgb(72, 119, 159);"></circle>
</g>
</g>
</g>
</g>
</svg>
Instead of drawing a green fill I'm currently drawing a red outline. What you should be able to see is that the red outline correctly surrounds the larger circle (planet) but goes vertically up instead of around the smaller circle (moon).
It appears as thought we're just missing a rotation, but the original prototype I built doesn't know about a rotation, just the center of each circle. In this case this should be really simple:
Moon
var tempMoon = { x: 0, y: 0, r: 32 };
Always located at (0, 0) as this circle sits in the center of the group which the path will be appended to
Planet
var tempPlanet = { x: -181.77581967381693, y: -144.9613789321555, r: 152 };
The planet is at the center of the group, which also contains the moon group. Therefore it's location is always just an inverse translation which positions the group containing the moon
I believe the locations are correct (I've tried adding circles on the moon layer to confirm they are in the correct place - which they are). I feel that this must be somehow down to the groups but I still can't pinpoint why this isn't rendering with the correct orientation.
Unfortunately it seems that I was missing a translate and rotate in the code toward the end that I'd missed previously for some reason. Including this in made it work as expected.
Trying to zoom to the cursor's position. I'm translating the image as I zoom (scale), but haven't got things working properly.
If you try the demo, you'll not that if you zoom to one location, the move the mouse and zoom to another location, the circle jumps.
jsFiddle: http://jsfiddle.net/nadirabid/f06n05ep/9/
function setCTM(element, matrix) {
var m = matrix;
var s = "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + m.e + "," + m.f + ")";
element.setAttributeNS(null, "transform", s);
}
var svgEl = document.getElementById('svg');
var zoomEl = document.getElementById('zoom');
var zoomScale = 1;
svgEl.addEventListener('wheel', function(e) {
var delta = e.wheelDeltaY;
zoomScale = Math.max(0.5, zoomScale - (delta / 2200));
zoomScale = Math.min(zoomScale, 1.5);
var p = svgEl.createSVGPoint();
p.x = e.clientX;
p.y = e.clientY;
p = p.matrixTransform(svgEl.getCTM().inverse());
var zoomMat = svgEl.createSVGMatrix()
.translate(p.x, p.y)
.scale(zoomScale)
.translate(-p.x, -p.y);
setCTM(zoomEl, zoomMat);
});
svg {
background-color: #eee;
}
body {
overflow: hidden;
}
<svg id="svg" width="400" height="400">
<g id="zoom">
<circle r="40" cx="200" cy="200"></circle>
</g>
</svg>
This is happening because you are replacing the old matrix completely without taking into account the previous "zoom history".
What you should be doing is reading (or remembering) the old matrix and then apply the new translate and scale operations to that.
I have 2 coordinates x and y of a point. I want to calculate the angle between three points, say A,B,C.
Now for the B point I do not have a pixel which contains the 2 coordinates instead I have the pixel, how can I get a single pixel which I can use in my formula.
function find_angle(A,B,C) {
var AB = Math.sqrt(Math.pow(B.x-A.x,2)+ Math.pow(B.y-A.y,2));
var BC = Math.sqrt(Math.pow(B.x-C.x,2)+ Math.pow(B.y-C.y,2));
var AC = Math.sqrt(Math.pow(C.x-A.x,2)+ Math.pow(C.y-A.y,2));
var abc = (BC*BC)+ (AB*AB)-(AC*AC);
var x = abc/(2*BC*AB);
var Angle = FastInt((Math.acos(x) * 180/3.14159));
document.getElementById("Angle").value = Angle;
}
How to proceed with this.
A is changing every time I move the point and I have the updated coordinates as well but I am not able to get the whole pixel I can use in the formula to calculate the new angle.
If I understand what you are asking - you want to create a calculator for the angle formed between
3 dots (A, B middle, C).
Your function should work for the final calculation but you need to recall the function every time
a point has moved.
I created a nice fiddle to demonstrate how you can achieve it with : jQuery, jQuery-ui, html.
I used the draggable() plugin of the UI library to allow the user to manually drag the dots around
And I'm recalculating the angle while dragging.
Take a look: COOL DEMO JSFIDDLE
The CODE ( you will find all HTML & CSS in the demo):
$(function(){
//Def Position values:
var defA = { top:20, left:220 };
var defB = { top:75, left:20 };
var defC = { top:200, left:220 };
//Holds the degree symbol:
var degree_symbol = $('<div>').html('゜').text();
//Point draggable attachment.
$(".point").draggable({
containment: "parent",
drag: function() {
set_result(); //Recalculate
},
stop: function() {
set_result(); //Recalculate
}
});
//Default position:
reset_pos();
//Reset button click event:
$("#reset").click(function(){ reset_pos(); });
//Calculate position of points and updates:
function set_result() {
var A = get_middle("A");
var B = get_middle("B");
var C = get_middle("C");
angle = find_angle(A,B,C);
$("#angle").val(angle + degree_symbol);
connect_line("AB");
connect_line("CB");
}
//Angle calculate:
function find_angle(A,B,C) {
var AB = Math.sqrt(Math.pow(B.x-A.x,2)+ Math.pow(B.y-A.y,2));
var BC = Math.sqrt(Math.pow(B.x-C.x,2)+ Math.pow(B.y-C.y,2));
var AC = Math.sqrt(Math.pow(C.x-A.x,2)+ Math.pow(C.y-A.y,2));
radians = Math.acos((BC*BC+AB*AB-AC*AC)/(2*BC*AB)); //Radians
degree = radians * (180/Math.PI); //Degrees
return degree.toFixed(3);
}
//Default position:
function reset_pos() {
$("#A").css(defA);
$("#B").css(defB);
$("#C").css(defC);
set_result();
}
//Add lines and draw them:
function connect_line(points) {
var off1 = null;
var offB = get_middle("B");
var thickness = 4;
switch (points) {
case "AB": off1 = get_middle("A"); break;
case "CB": off1 = get_middle("C"); break;
}
var length = Math.sqrt(
((offB.x-off1.x) * (offB.x-off1.x)) +
((offB.y-off1.y) * (offB.y-off1.y))
);
var cx = ((off1.x + offB.x)/2) - (length/2);
var cy = ((off1.y + offB.y)/2) - (thickness/2);
var angle = Math.atan2((offB.y-off1.y),(offB.x-off1.x))*(180/Math.PI);
var htmlLine = "<div id='" + points + "' class='line' " +
"style='padding:0px; margin:0px; height:" + thickness + "px; " +
"line-height:1px; position:absolute; left:" + cx + "px; " +
"top:" + cy + "px; width:" + length + "px; " +
"-moz-transform:rotate(" + angle + "deg); " +
"-webkit-transform:rotate(" + angle + "deg); " +
"-o-transform:rotate(" + angle + "deg); " +
"-ms-transform:rotate(" + angle + "deg); " +
"transform:rotate(" + angle + "deg);' />";
$('#testBoard').find("#" + points).remove();
$('#testBoard').append(htmlLine);
}
//Get Position (center of the point):
function get_middle(el) {
var _x = Number($("#" + el).css("left").replace(/[^-\d\.]/g, ''));
var _y = Number($("#" + el).css("top").replace(/[^-\d\.]/g, ''));
var _w = $("#" + el).width();
var _h = $("#" + el).height();
return {
y: _y + (_h/2),
x: _x + (_w/2),
width: _w,
height: _h
};
}
});
This Code requires jQuery & jQuery-UI. Don't forget to include them if you test it locally.
Have fun!
I have a paper with 400 x 500 in size. I am trying to divide this into 20 x 20 pixels with below code
var dpH = 500, dpW = 400, drawPad = new Raphael(document.getElementById('p'),
dpW, dpH);
for ( var i = 0; i <= dpH / 20; i++) {
drawPad.path("M" + 1 + " " + ((i * 20) + 1) + "L" + dpW + " "
+ ((i * 20) + 1));
}
for ( var j = 0; j <= (dpW / 20); j++) {
drawPad.path("M" + ((j * 20) + 1) + " " + 1 + "L" + ((j * 20) + 1) + " "
+ dpH);
}
And HTML markup is like below
<div id="p" style="background-image:url(image.png)"> </div>
with same height and width of Background Image.
My original requirement was making the image.png as Rapheal paper. But I was failed to do that. So I made it as background-image to the DIV#P. Then converted the DIv to Paper.
Here are my questions related to above
Does all the pixels of Background-Image and DIV match with each other?
The way I did above is to classify the total paper into 20x20 pixel divisions. Is that correct way of doing?
What is the width of the drawn line?
Please help me on this.
Ok, so if I understand you correctly; What you really want is to get the raw image data for 20x20 squares of the image.
Here's how you can extract image data with Canvas (also on jsFiddle):
var dpH = 500,
dpW = 400,
ctx = document.getElementById('p').getContext('2d'),
exportData = function() {
var data;
for (var y=0, yl=dpH/20; y<yl; y++) {
for (var x=0, xl=dpW/20; x<xl; x++) {
imgData = ctx.getImageData(x*20, y*20, 20, 20).data;
console.log("Image data for " + x*20 + ", " + y*20, imgData);
// data is an array with 4 values pr pixel
// Top left pixel in the 20x20 square
r = imgData[0]; // red
g = imgData[1]; // green
b = imgData[2]; // blue
a = imgData[3]; // alpha
console.log("RGBa of " + x*20 + ", " + y*20 + ": ", r, g, b, a);
}
}
},
drawImage = function() {
ctx.drawImage(this, 0, 0);
exportData(this);
};
var img = new Image();
img.onload = drawImage;
img.src = "image.png"; // has to be on the same domain
** Original answer **
The result is a DIV with an SVG-element inside, and a background image behind it. The browser (if it supports SVG) will render them on top of each other. Do you want to extract pixel values? If so, you have to do this through HTML5 Canvas instead of SVG.
Sorry, I don't understand. What are you trying to accomplish? Do you want the pixel data for 20x20 squares? With Raphael you are just drawing lines on top of the picture.
The defaut with of a path is 1 pixels. You can change this by setting an attribute on the path. Example (also on jsfiddle.net):
var dpH = 500,
dpW = 400,
drawPad = Raphael(document.getElementById('p'), dpW, dpH),
style = {
"stroke" : "#fff", // white
"stroke-width" : 2 // default 1
};
for ( var i = 0; i <= dpH / 20; i++) {
drawPad.path("M" + 1 + " " + ((i * 20) + 1) + "L" + dpW + " "
+ ((i * 20) + 1)).attr(style);
}
for ( var j = 0; j <= (dpW / 20); j++) {
drawPad.path("M" + ((j * 20) + 1) + " " + 1 + "L" + ((j * 20) + 1) + " "
+ dpH).attr(style);
}