"Mapping" arrows to characters - php

I don't really know how to title this, so sorry if the title was confusing.
I would like a way to draw various kinds/orientations of arrows depending on the lengths of the strings they're pointing to (amongst other factors). See the picture below.
I can't just make an image (like this one) because the numbers and letters will be randomly generated. So, I won't know if a number is a 1, 2, or 3 digit number (or if it will have letters attached to it).
Basically, is there a way to connect the centers of "nodes" (probably the wrong word, but I don't know what else to say) with the start and end of an arrow?
I'm open to the full gamut of webprogramming for this. Javascript libraries, Raphael.js, canvas.... best idea wins!

This design maps arrows to & from any specified characters in a math phrase
This design uses html canvas to draw the text math phrases and connected arrows.
It works by having you specify any character inside a math phrase and calling for either an up or down arrow to be drawn on that character.
// draw an up arrow on the current phrase as character#1
drawUpArrow(phrase,30,80,1,"red");
// draw a down arrow on the current phrase at character#5
drawDownArrow(phrase,30,80,5,"green");
You can specify as many arrows as you need.
// draw arrow on characters #1,3,5,7
drawUpArrow(phrase,30,80,1,"red");
drawDownArrow(phrase,30,80,3,"green");
drawDownArrow(phrase,30,80,5,"green");
drawDownArrow(phrase,30,80,7,"green");
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/dUexE/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:15px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.font="14pt Verdana";
var phrase="(5c + 3)(7n + 2)";
var connectorPoints=[]
var connectorPoints2=[]
// draw start-arrow at character #1
// draw end-arrows at characters #5 and #12
drawPhrase(phrase,30,80);
connectorPoints.push(drawUpArrow(phrase,30,80,2,"red"));
connectorPoints.push(drawDownArrow(phrase,30,80,10,"green"));
connectorPoints.push(drawDownArrow(phrase,30,80,15,"green"));
temporaryConnector(connectorPoints,"green");
connectorPoints2.push(drawDownArrowUnder(phrase,30,80,7,"red"));
connectorPoints2.push(drawUpArrowUnder(phrase,30,80,10,"green"));
connectorPoints2.push(drawUpArrowUnder(phrase,30,80,15,"green"));
temporaryConnector(connectorPoints2,"green");
// draw the phrase at X/Y
function drawPhrase(text,x,y){
ctx.fillStyle="black";
ctx.fillText(text,x,y);
}
function calcMidX(text,x,letterNumber){
var text1=text.substr(0,letterNumber-1);
var text2=text.substr(0,letterNumber);
var startX=ctx.measureText(text1).width;
var endX=ctx.measureText(text2).width;
var midX=startX+(endX-startX)/2;
return(midX);
}
function drawArrow(x,y,y1,y2,y3,color){
// arrowhead
ctx.beginPath();
ctx.moveTo(x,y-y1);
ctx.lineTo(x-5,y-y2);
ctx.lineTo(x+5,y-y2);
ctx.closePath();
ctx.fillStyle=color;
ctx.fill();
// arrowtail
ctx.beginPath();
ctx.moveTo(x,y-y2);
ctx.lineTo(x,y-y3);
ctx.strokeStyle=color;
ctx.lineWidth=3;
ctx.stroke();
}
// draw a down-arrow at the specified letterNumber
function drawDownArrow(text,x,y,letterNumber,color){
x+=calcMidX(text,x,letterNumber);
drawArrow(x,y,18,28,35,color);
return({x:x,y:y-35});
}
// draw an up-arrow at the specified letterNumber
function drawUpArrow(text,x,y,letterNumber,color){
x+=calcMidX(text,x,letterNumber);
drawArrow(x,y,35,25,18,color);
return({x:x,y:y-35});
}
// draw a down-arrow at the specified letterNumber
function drawDownArrowUnder(text,x,y,letterNumber,color){
x+=calcMidX(text,x,letterNumber);
drawArrow(x,y,-22,-12,-5,color);
return({x:x,y:y+22});
}
// draw an up-arrow at the specified letterNumber
function drawUpArrowUnder(text,x,y,letterNumber,color){
x+=calcMidX(text,x,letterNumber);
drawArrow(x,y,-5,-15,-22,color);
return({x:x,y:y+22});
}
function temporaryConnector(aConnector,color){
var pt1=aConnector[0];
var pt2=aConnector[aConnector.length-1];
ctx.beginPath();
ctx.moveTo(pt1.x,pt1.y);
ctx.lineTo(pt2.x+2,pt2.y);
ctx.strokeStyle=color;
ctx.lineWidth=3;
ctx.stroke();
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Red arrow shows start</p>
<p>Green arrow shows end</p>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
EDIT FROM OP: If anyone is interested, here is the final fiddle I ended up using: http://jsfiddle.net/53mQD/2/ I took out the red arrows and replaced them with lines. All credit goes to markE.

Related

enter mathematical formulas in html textbox and storing it to mysql database

I need to display mathematical formulas in text input and store it in database
formulas like given in below image
http://xahlee.info/math/i/math_formula_MathJax.png
when i copy any formula to text box it's converted to normal text, i need to disaplay formula as it is.
There are HTML characters for mathematical symbols, but to organise them similar to your image is not possible using plain HTML.
You could have a look into using the HTML Canvas API with JavaScript to create the result you need. You could even store the JavaScript in your MySQL Database.
Small example using your image as reference:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// k above sigma
ctx.font = "15px Arial";
ctx.fillText("k", 20, 20);
// sigma
ctx.font = "40px Arial";
ctx.fillText("\u03A3", 10, 55);
// n=1 below sigma
ctx.font = "15px Arial";
ctx.fillText("n=1", 10, 70);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;"></canvas>
</body>
</html>

PHP: d3.js script does not display anything

Problem: I've got the following code, that runs fine as a standalone .html file. Now, I wish to display this within a .php file. Inside the .php file, I've copy-pasted the same code.
There are some header/footer and other html in the main page where this .php file is to be displayed. However, when I run it But other than the line, "Testing", the chart does not display.
What additional changes should be done ?
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<div>
<h4>Testing</h4>
</div>
<!-- <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.4.5"></script> -->
<script src="d3.v3.js"></script>
<!-- Source for example located at: http://bl.ocks.org/1203641 -->
<style type="text/css">
.slice text {
font-size: 16pt;
font-family: Arial;
}
</style>
<script>
var canvasWidth = 500, //width
canvasHeight = 700, //height
outerRadius = 200, //radius
color = d3.scale.category20(); //builtin range of colors
var dataSet = [
{"legendLabel":"Your child's Percentile", "magnitude":90},
{"legendLabel":"Ahead of your child", "magnitude":10},
// {"legendLabel":"Three", "magnitude":50},
// {"legendLabel":"Four", "magnitude":16},
// {"legendLabel":"Five", "magnitude":50},
// {"legendLabel":"Six", "magnitude":8},
// {"legendLabel":"Seven", "magnitude":30}
];
var vis = d3.select("body")
.append("svg:svg") //create the SVG element inside the <body>
.data([dataSet]) //associate our data with the document
.attr("width", canvasWidth) //set the width of the canvas
.attr("height", canvasHeight) //set the height of the canvas
.append("svg:g") //make a group to hold our pie chart
.attr("transform", "translate(" + 1.5*outerRadius + "," + 1.5*outerRadius + ")") // relocate center of pie to 'outerRadius,outerRadius'
// This will create <path> elements for us using arc data...
var arc = d3.svg.arc()
.outerRadius(outerRadius);
var pie = d3.layout.pie() //this will create arc data for us given a list of values
.value(function(d) { return d.magnitude; }) // Binding each value to the pie
.sort( function(d) { return null; } );
// Select all <g> elements with class slice (there aren't any yet)
var arcs = vis.selectAll("g.slice")
// Associate the generated pie data (an array of arcs, each having startAngle,
// endAngle and value properties)
.data(pie)
// This will create <g> elements for every "extra" data element that should be associated
// with a selection. The result is creating a <g> for every object in the data array
.enter()
// Create a group to hold each slice (we will have a <path> and a <text>
// element associated with each slice)
.append("svg:g")
.attr("class", "slice"); //allow us to style things in the slices (like text)
arcs.append("svg:path")
//set the color for each slice to be chosen from the color function defined above
.attr("fill", function(d, i) { return color(i); } )
//this creates the actual SVG path using the associated data (pie) with the arc drawing function
.attr("d", arc);
// Add a legendLabel to each arc slice...
arcs.append("svg:text")
.attr("transform", function(d) { //set the label's origin to the center of the arc
//we have to make sure to set these before calling arc.centroid
d.outerRadius = outerRadius + 50; // Set Outer Coordinate
d.innerRadius = outerRadius + 45; // Set Inner Coordinate
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle") //center the text on it's origin
.style("fill", "Purple")
.style("font", "bold 12px Arial")
.text(function(d, i) { return dataSet[i].legendLabel; }); //get the label from our original data array
// Add a magnitude value to the larger arcs, translated to the arc centroid and rotated.
arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; }).append("svg:text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
//.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")"; })
.attr("transform", function(d) { //set the label's origin to the center of the arc
//we have to make sure to set these before calling arc.centroid
d.outerRadius = outerRadius; // Set Outer Coordinate
d.innerRadius = outerRadius/2; // Set Inner Coordinate
return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")";
})
.style("fill", "White")
.style("font", "bold 12px Arial")
.text(function(d) { return d.data.magnitude; });
// Computes the angle of an arc, converting from radians to degrees.
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
</script>
</meta>
</head>
</html>
Works fine for me. The only difference is that I replaced your script tags with remote ones
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://dimplejs.org/dist/dimple.v2.1.0.min.js"></script>
If you are including this file from another PHP file, delete doctype, html, body and head tags - they can't be duplicate in generated file.
update: by the way, div tags don't belong to head section

how to fill a image with pattern

let's say i have a image !
now i want to fill that image with
and my final image should look like this
how to do it?
so far i was able to change the color of that image but was not able to fill pattern.
can i do it with html5 canvas (pattern)? is there any way to do it with php or any web platform.
Use these steps to create simulate applying a mapped pattern to your shirt:
Create a high-contrast version of your shirt.
DrawImage that shirt onto the canvas
Set globalCompositeOperation to “source-atop”
(any new drawing will only appear where the shirt image is opaque)
Create a pattern from your checkered image
Fill the canvas with the checkered pattern
(it will only appear in the non-transparent shirt)
Set the globalAlpha to a very low value
Repeatedly drawImage the high-contrast shirt
(this effectively superimposes the shirt “wrinkles”)
For a better solution
Create a “bump-map” of the shirt and apply it with the checkered pattern in three.js
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/kzfKD/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img1=new Image();
var img=new Image();
img.onload=function(){
img1.onload=function(){
start();
}
img1.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/4jiSz1.png";
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/BooMu1.png";
function start(){
ctx.drawImage(img1,0,0);
ctx.globalCompositeOperation="source-atop";
ctx.globalAlpha=.85;
var pattern = ctx.createPattern(img, 'repeat');
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = pattern;
ctx.fill();
ctx.globalAlpha=.15;
ctx.drawImage(img1,0,0);
ctx.drawImage(img1,0,0);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=436 height=567></canvas>
</body>
</html>
As suggested in the comments on your question, one approach is to overlay DOM elements -- the top DOM element should be a PNG with transparency, and the bottom one should be your background pattern. This also works (and it's faster since you don't have to compute the combined image) but provides a little less flexibility in terms of the way the images are combined. With the canvas method, you can use any blend mode you want.
A second option which is not supported by most browsers yet is to use CSS background blend modes. This would allow you to create a PNG image with transparency, assign it a background color, and use blending with CSS. This is fast and only requires one DOM element.
A third approach is to use canvases. (Edit: markE's canvas approach is faster and simpler.) I implemented one canvas-based approach in this JSFiddle: http://jsfiddle.net/IceCreamYou/uzzLa/ -- here's the gist:
// Get the base image data
var image_data = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
var image_data_array = image_data.data;
// Get the pattern image data
var overlay_data = ovlyCtx.getImageData(0, 0, ovlyCtx.canvas.width, ovlyCtx.canvas.height).data;
// Loop over the pixels in the base image and merge the colors
for (var i = 0, j = image_data_array.length; i < j; i+=4) {
// Only merge when the base image pixel is nontransparent
// Alternatively you could implement a border-checking algorithm depending on your needs
if (image_data_array[i+3] > 0) {
image_data_array[i+0] = combine(image_data_array[i+0], overlay_data[i+0]); // r
image_data_array[i+1] = combine(image_data_array[i+1], overlay_data[i+1]); // g
image_data_array[i+2] = combine(image_data_array[i+2], overlay_data[i+2]); // b
}
}
// Write the image data back to the canvas
ctx.putImageData(image_data, 0, 0);
What it does is create one canvas with the base image and a second canvas that tiles your pattern image, then uses the pixel data to overlay the pattern over the base when the base pixels are nontransparent.

change input button style using javascript on click

I wanted to change the style of the button I'm using every time I clicked that button and together change it's text. Problem is I wanted to do it using and external javascript which I'm not that familiar with it's syntax. To elaborate what I wanted to do is to have a button having a text displaying like: Very Good, Good, Moderate, Failed. Each of the text has it's own assigned gradient color using CSS let's say a gradient of Green for Very Good, Yellow for Good, Orange for Moderate and Red for failed. Tried searching for it but I only landed on an irrelevant posts. What I think is that I need to make a button with on click and everytime I click the javascript will add int values from 0 and reset back to 0 after it reaches 3. then I think I can use case for the css class assigning like this.style="failed" Well I don't know if this is possible.
UPDATE:
After doing some research I've managed to do something about the changing texts (using javascript alone) but not yet the class part since I think the class is a keyword in javascript. here's my script so far:
function buttonChange(){
var button = document.getElementById("stats");
switch (button.value)
{
case "Very Good":
button.value="Good";
break;
case "Good":
button.value="Moderate";
break;
case "Moderate":
button.value="Failed";
break;
default:
button.value="Very Good";
}
}
now the problem is the style. :)
Using jQuery your code could look something like this:
var values = new Array('Very Good', 'Good', 'Moderate', 'Failed');
var colors = new Array('lime', 'yellow', 'orange', 'red');
$('#rate').click(function() {
// current index is stored in data attribute
var idx = $(this).data('value') + 1;
// last value was selected -> go back to first one
if (idx >= values.length) {
idx = 0;
}
// update data attribute with current index
$(this).data('value', idx);
// update button text
$(this).val(values[idx]);
// update button background color
$(this).css('background-color', colors[idx]);
});​
See this FIDDLE.
have a look at this:
Change an element's class with JavaScript
I think that your CSS should have all the styles for gradients and stuff like this:
.VeryGood {//gradient for very good
}
.Good {//gradient for good
}
.Moderate {//gradient for moderate
}
.Failed { //gradient for failed
}
and then, use this javascript and html :
<script type="text/javascript">
var i = 1; //change to 0 if element dosen't need to have any class by default
var classArray = new Array();
classArray[0] = 'VeryGood';
classArray[1] = 'Good';
classArray[2] = 'Moderate';
classArray[3] = 'Failed';
function changeClass()
{
document.getElementById("MyElement").className = classArray[i];
i++;
if(i>=3){
i=0;
}
}
</script>
...
<button onclick="changeClass()">My Button</button>
now, the array key i increases every time the button is clicked, so by default, you can have your element's class as VeryGood, and every time the button is clicked, it advances to next class, so after VeryGood comes Good then Moderate then Failed, ithe it resets itself to VeryGood. hope this is what you are looking for :)
Here is a jQuery solution to cycle through the button text and the background colour for the four states:
<!doctype html>
<html>
<head>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var states = ['Very Good', 'Good', 'Moderate', 'Failed'];
var colors = ['green', 'Yellow', 'orange', 'red'];
var index = 0;
$('body').on('click', '#button', function(){
index = ++index%4;
$("#button").html(states[index]);
$("#button").css('background-color',colors[index]);
});
});
</script>
</head>
<body>
<button id="button" style="background-color:green"; type="button">Very Good</button>
</body>
</html>
Note the modulus (%) operator which simplifies the circular increment of 'index' from 0 to 3.

Not sure why jQuery isn't getting the variable information

The values don't seem to be coming out and showing up on the page. It should be creating divs that pop up with the google_color and the background set to the hex value.
The app is suppose to take pixel image data and match it to my swatch library known as formatted_colors.js, which is an array. The array looks like this:
var colors = [];
colors["000000"] = "black"; colors["100000"] = "black"; colors["200000"] = "black";
Maybe I'm not suppose to use the .each function? Although it is a loop.
Here is a snippet:
<div class="rounded_color" hex="<?php echo $css_color ?>" xy="<?php echo $x.$y ?>"></div>
<div id="<?php echo $x.$y ?>"></div>
<script type="text/javascript" src="jquery-1.6.2.js"></script>
<script src="formatted_colors.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//iterate through pixels and match rounded color to array in formatted_colors.js
$(document).ready(function() {
$(".rounded_color").each(function(){
var google_color = getColor($(this).attr("hex")); // finds a match of "hex" value in formatted_colors.js and return name to google_color
$('#'+$(this).attr("hex")).html(google_color); // set the div's html to name which is google_color
alert('#'+$(this).attr("id")); //testing if value is there, but shows #undefined
$('#'+$(this).attr("hex")).css('background-color:', google_color);
})
// get name of color function from formatted_colors.js
function getColor(target_color){
if (colors[target_color] == undefined) { // not found
return "no match";
} else {
return colors[target_color];
}
} // end getColor function
}) // end ready function
</script>
Sorry, I'm new to this so I'm not sure what to do exactly now.
Here is my entire code: http://pastebin.com/HEB3TWZP
Thanks in advance!
You don't need to concatenate #. this is the current element in the iteration.
Also you might want to do something like var $this = $(this); Cleans up your code and you aren't recreating the jQuery object over and over again within the same iteration.

Categories