How to change Y axis labels - html

I am using Chartjs to make line chart.How can I change the y axis labels to colours? (i.e. red for 1, green for 2, black for 3, ..)

UPDATE i've now added this feature into my fork of chartjs at https://github.com/leighquince/Chart.js, meanign you would not have to override or extend a new chart type. Just pass the option in like normal, here is an example http://fiddle.jshell.net/leighking2/jLzvhf4f/
So this could be achieved by overriding the scales draw method to run a custom function we provide when declaring the chart rather than just adding.
Below is the snippet but just as an explanation here is what has happened
created a new chart and overridden the buildScale method to pass a new option called customYLabel. this will be the option you pass to your chart when you declare it and it has 4 parameters; the value of the label, x position, y position, the canvas, this index of the label
the build scale also makes use of a custom scale
create a custom scale which overrides the normal scales draw method to check for this customYLabel option and uses it if present
the reset is normal, what you customYLabel does is up to you but it should at the very least call `ctx.fillText(value,x,y) so that the label is drawn on the canvas. In the below example i colour the label based on it's index but the options there many.
(here is a fiddle as well if thats easier to view http://fiddle.jshell.net/leighking2/2cac5t34/)
//extract helpers so we can use them in our custom scale class
var helpers = Chart.helpers,
each = helpers.each,
aliasPixel = helpers.aliasPixel,
toRadians = helpers.radians;
//new line chart which has an overridden buildscale that will pass the new option customYLabel
Chart.types.Line.extend({
// Passing in a name registers this chart in the Chart namespace in the same way
name: "LineAlt",
initialize: function (data) {
Chart.types.Line.prototype.initialize.apply(this, arguments);
},
buildScale: function (labels) {
var self = this;
var dataTotal = function () {
var values = [];
self.eachPoints(function (point) {
values.push(point.value);
});
return values;
};
var scaleOptions = {
templateString: this.options.scaleLabel,
height: this.chart.height,
width: this.chart.width,
ctx: this.chart.ctx,
textColor: this.options.scaleFontColor,
fontSize: this.options.scaleFontSize,
fontStyle: this.options.scaleFontStyle,
fontFamily: this.options.scaleFontFamily,
valuesCount: labels.length,
beginAtZero: this.options.scaleBeginAtZero,
integersOnly: this.options.scaleIntegersOnly,
//new options for custom y label
customYLabel: this.options.customYLabel,
calculateYRange: function (currentHeight) {
var updatedRanges = helpers.calculateScaleRange(
dataTotal(),
currentHeight,
this.fontSize,
this.beginAtZero,
this.integersOnly);
helpers.extend(this, updatedRanges);
},
xLabels: labels,
font: helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth: this.options.scaleLineWidth,
lineColor: this.options.scaleLineColor,
showHorizontalLines: this.options.scaleShowHorizontalLines,
showVerticalLines: this.options.scaleShowVerticalLines,
gridLineWidth: (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor: (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
showLabels: this.options.scaleShowLabels,
display: this.options.showScale
};
if (this.options.scaleOverride) {
helpers.extend(scaleOptions, {
calculateYRange: helpers.noop,
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
});
}
this.scale = new Chart.CustomScale(scaleOptions);
},
});
//custom scale to use new customYLabel option
Chart.CustomScale = Chart.Scale.extend({
draw: function () {
var ctx = this.ctx,
yLabelGap = (this.endPoint - this.startPoint) / this.steps,
xStart = Math.round(this.xScalePaddingLeft);
if (this.display) {
ctx.fillStyle = this.textColor;
ctx.font = this.font;
each(this.yLabels, function (labelString, index) {
var yLabelCenter = this.endPoint - (yLabelGap * index),
linePositionY = Math.round(yLabelCenter),
drawHorizontalLine = this.showHorizontalLines;
ctx.textAlign = "right";
ctx.textBaseline = "middle";
if (this.showLabels) {
//if we have a customYLabel use it passing the value, x, y , canvas and index
if (this.customYLabel) {
this.customYLabel(labelString, xStart - 10, yLabelCenter, ctx, index);
} else {
ctx.fillText(labelString, xStart - 10, yLabelCenter);
}
}
// This is X axis, so draw it
if (index === 0 && !drawHorizontalLine) {
drawHorizontalLine = true;
}
if (drawHorizontalLine) {
ctx.beginPath();
}
if (index > 0) {
// This is a grid line in the centre, so drop that
ctx.lineWidth = this.gridLineWidth;
ctx.strokeStyle = this.gridLineColor;
} else {
// This is the first line on the scale
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
}
linePositionY += helpers.aliasPixel(ctx.lineWidth);
if (drawHorizontalLine) {
ctx.moveTo(xStart, linePositionY);
ctx.lineTo(this.width, linePositionY);
ctx.stroke();
ctx.closePath();
}
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
ctx.beginPath();
ctx.moveTo(xStart - 5, linePositionY);
ctx.lineTo(xStart, linePositionY);
ctx.stroke();
ctx.closePath();
}, this);
each(this.xLabels, function (label, index) {
var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
// Check to see if line/bar here and decide where to place the line
linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
isRotated = (this.xLabelRotation > 0),
drawVerticalLine = this.showVerticalLines;
// This is Y axis, so draw it
if (index === 0 && !drawVerticalLine) {
drawVerticalLine = true;
}
if (drawVerticalLine) {
ctx.beginPath();
}
if (index > 0) {
// This is a grid line in the centre, so drop that
ctx.lineWidth = this.gridLineWidth;
ctx.strokeStyle = this.gridLineColor;
} else {
// This is the first line on the scale
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
}
if (drawVerticalLine) {
ctx.moveTo(linePos, this.endPoint);
ctx.lineTo(linePos, this.startPoint - 3);
ctx.stroke();
ctx.closePath();
}
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
// Small lines at the bottom of the base grid line
ctx.beginPath();
ctx.moveTo(linePos, this.endPoint);
ctx.lineTo(linePos, this.endPoint + 5);
ctx.stroke();
ctx.closePath();
ctx.save();
ctx.translate(xPos, (isRotated) ? this.endPoint + 12 : this.endPoint + 8);
ctx.rotate(toRadians(this.xLabelRotation) * -1);
ctx.font = this.font;
ctx.textAlign = (isRotated) ? "right" : "center";
ctx.textBaseline = (isRotated) ? "middle" : "top";
ctx.fillText(label, 0, 0);
ctx.restore();
}, this);
}
}
});
var randomScalingFactor = function () {
return Math.round(Math.random() * 100)
};
//example colour generator from
//https://www.designedbyaturtle.co.uk/2014/convert-string-to-hexidecimal-colour-with-javascript-vanilla/
// Convert an int to hexadecimal with a max length
// of six characters.
var intToARGB = function (i) {
var h = ((i >> 24) & 0xFF).toString(16) + ((i >> 16) & 0xFF).toString(16) + ((i >> 8) & 0xFF).toString(16) + (i & 0xFF).toString(16);
return h.substring(0, 6);
}
var lineChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
}, {
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [null, 10, null, null, 60, null, null]
}]
}
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart(ctx).LineAlt(lineChartData, {
//example of how this can be used, could use the value instead of the index
customYLabel: function (value, x, y, ctx, index) {
var defaultStyle = ctx.fillStyle;
ctx.fillStyle = '#' + intToARGB(index * 123456);
ctx.fillText(value, x, y);
ctx.fillStyle = defaultStyle;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.1/Chart.js"></script>
<div style="width:100%">
<div>
<canvas id="canvas" height="200" width="600"></canvas>
</div>
</div>

Related

I am trying to set this HTML code to a chromebook background. Is this possible?

I am trying to set this HTML code to a Chromebook background. Is this possible? I also don't want to have to use any extensions.
<style>*{
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html, body{
height: 100%;
margin: 0;
padding: 0;
background-color: #333;
overflow: hidden;
}
canvas{
background-color: #000;
}</style>
<div class="container">
<div class="row">
<canvas id="nokey" width="800" height="800">
</canvas>
</div>
</div>
<script>
var canvas = document.getElementById('nokey'),
can_w = parseInt(canvas.getAttribute('width')),
can_h = parseInt(canvas.getAttribute('height')),
ctx = canvas.getContext('2d');
// console.log(typeof can_w);
var ball = {
x: 0,
y: 0,
vx: 0,
vy: 0,
r: 0,
alpha: 1,
phase: 0
},
ball_color = {
r: 207,
g: 255,
b: 4
},
R = 2,
balls = [],
alpha_f = 0.03,
alpha_phase = 0,
// Line
link_line_width = 0.8,
dis_limit = 260,
add_mouse_point = true,
mouse_in = false,
mouse_ball = {
x: 0,
y: 0,
vx: 0,
vy: 0,
r: 0,
type: 'mouse'
};
// Random speed
function getRandomSpeed(pos){
var min = -1,
max = 1;
switch(pos){
case 'top':
return [randomNumFrom(min, max), randomNumFrom(0.1, max)];
break;
case 'right':
return [randomNumFrom(min, -0.1), randomNumFrom(min, max)];
break;
case 'bottom':
return [randomNumFrom(min, max), randomNumFrom(min, -0.1)];
break;
case 'left':
return [randomNumFrom(0.1, max), randomNumFrom(min, max)];
break;
default:
return;
break;
}
}
function randomArrayItem(arr){
return arr[Math.floor(Math.random() * arr.length)];
}
function randomNumFrom(min, max){
return Math.random()*(max - min) + min;
}
console.log(randomNumFrom(0, 10));
// Random Ball
function getRandomBall(){
var pos = randomArrayItem(['top', 'right', 'bottom', 'left']);
switch(pos){
case 'top':
return {
x: randomSidePos(can_w),
y: -R,
vx: getRandomSpeed('top')[0],
vy: getRandomSpeed('top')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
}
break;
case 'right':
return {
x: can_w + R,
y: randomSidePos(can_h),
vx: getRandomSpeed('right')[0],
vy: getRandomSpeed('right')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
}
break;
case 'bottom':
return {
x: randomSidePos(can_w),
y: can_h + R,
vx: getRandomSpeed('bottom')[0],
vy: getRandomSpeed('bottom')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
}
break;
case 'left':
return {
x: -R,
y: randomSidePos(can_h),
vx: getRandomSpeed('left')[0],
vy: getRandomSpeed('left')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
}
break;
}
}
function randomSidePos(length){
return Math.ceil(Math.random() * length);
}
// Draw Ball
function renderBalls(){
Array.prototype.forEach.call(balls, function(b){
if(!b.hasOwnProperty('type')){
ctx.fillStyle = 'rgba('+ball_color.r+','+ball_color.g+','+ball_color.b+','+b.alpha+')';
ctx.beginPath();
ctx.arc(b.x, b.y, R, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
});
}
// Update balls
function updateBalls(){
var new_balls = [];
Array.prototype.forEach.call(balls, function(b){
b.x += b.vx;
b.y += b.vy;
if(b.x > -(50) && b.x < (can_w+50) && b.y > -(50) && b.y < (can_h+50)){
new_balls.push(b);
}
// alpha change
b.phase += alpha_f;
b.alpha = Math.abs(Math.cos(b.phase));
// console.log(b.alpha);
});
balls = new_balls.slice(0);
}
// loop alpha
function loopAlphaInf(){
}
// Draw lines
function renderLines(){
var fraction, alpha;
for (var i = 0; i < balls.length; i++) {
for (var j = i + 1; j < balls.length; j++) {
fraction = getDisOf(balls[i], balls[j]) / dis_limit;
if(fraction < 1){
alpha = (1 - fraction).toString();
ctx.strokeStyle = 'rgba(150,150,150,'+alpha+')';
ctx.lineWidth = link_line_width;
ctx.beginPath();
ctx.moveTo(balls[i].x, balls[i].y);
ctx.lineTo(balls[j].x, balls[j].y);
ctx.stroke();
ctx.closePath();
}
}
}
}
// calculate distance between two points
function getDisOf(b1, b2){
var delta_x = Math.abs(b1.x - b2.x),
delta_y = Math.abs(b1.y - b2.y);
return Math.sqrt(delta_x*delta_x + delta_y*delta_y);
}
// add balls if there a little balls
function addBallIfy(){
if(balls.length < 20){
balls.push(getRandomBall());
}
}
// Render
function render(){
ctx.clearRect(0, 0, can_w, can_h);
renderBalls();
renderLines();
updateBalls();
addBallIfy();
window.requestAnimationFrame(render);
}
// Init Balls
function initBalls(num){
for(var i = 1; i <= num; i++){
balls.push({
x: randomSidePos(can_w),
y: randomSidePos(can_h),
vx: getRandomSpeed('top')[0],
vy: getRandomSpeed('top')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
});
}
}
// Init Canvas
function initCanvas(){
canvas.setAttribute('width', window.innerWidth);
canvas.setAttribute('height', window.innerHeight);
can_w = parseInt(canvas.getAttribute('width'));
can_h = parseInt(canvas.getAttribute('height'));
}
window.addEventListener('resize', function(e){
console.log('Window Resize...');
initCanvas();
});
function goMovie(){
initCanvas();
initBalls(20);
window.requestAnimationFrame(render);
}
goMovie();
// Mouse effect
canvas.addEventListener('mouseenter', function(){
console.log('mouseenter');
mouse_in = true;
balls.push(mouse_ball);
});
canvas.addEventListener('mouseleave', function(){
console.log('mouseleave');
mouse_in = false;
var new_balls = [];
Array.prototype.forEach.call(balls, function(b){
if(!b.hasOwnProperty('type')){
new_balls.push(b);
}
});
balls = new_balls.slice(0);
});
canvas.addEventListener('mousemove', function(e){
var e = e || window.event;
mouse_ball.x = e.pageX;
mouse_ball.y = e.pageY;
// console.log(mouse_ball);
});
</script>
Since you said, "Chromebook." There's no native support for it as you're asking; without extension.
According to Google's Chromebook Help, they state only .png & .jpg backgrounds.
If you haven't yet, download an image (.png or .jpg) from the web that
you’d like as your wallpaper.
Also, referencing the crosexperts website, it states:
there’s no native support for moving wallpapers, we had to create an
engine — and editor — to make this possible. But, amazingly, it is
possible.
Chrome OS doesn’t support Live Wallpapers in any way.

Make canvas circle larger

I am new to using the canvas html tag and have put a countdown on my website that uses the canvas tag that I think makes the circle and it works ok but would like to make the circles larger but not sure how to do it, I got the coding from https://codepen.io/mdkroon/pen/dBweaL, below is the coding that I currently have. I can't work out how to make the circles larger, I can make the font larger but then the text does not fit in the circles.
<div id="countdown" data-date="2020-01-14" data-time="12:00:00">
<p><strong>Windows 7 End of Life Countdown</strong></p>
<div class="canvas-container" >
<canvas id="days"></canvas>
<canvas id="hours"></canvas>
<canvas id="minutes"></canvas>
<canvas id="seconds"></canvas>
</div>
</div>
<script>
// variables
var countdown = document.getElementById('countdown');
var endDate = countdown.dataset.date || '2020-01-14';
var endTime = countdown.dataset.time || '00:00:00';
var endCountdown = new Date(endDate + 'T' + endTime);
var timer;
var specs = {
'radius': 50,
'centerX': 50,
'centerY': 50,
'thickness': 10,
'offset': -Math.PI/2,
'color': '#1abc9c',
'bgColor': '#ccc',
'idFont': 'small-caps 400 10px Verdana',
'valueFont': 'bold 30px Verdana',
'fontColor': '#000'
};
var time = {
'millisecond': 1000,
'second': 60,
'minute': 60,
'hour': 24,
'day': 365
}
var info = {};
// canvas init
var canvasElements = Array.prototype.slice.call(document.querySelectorAll('canvas'));
var canvasCtx = [];
canvasElements.forEach( function(canvas, index) {
canvas.width = specs.centerX * 2;
canvas.height = specs.centerY * 2;
canvasCtx[index] = canvas.getContext('2d');
var name = canvas.id;
info[name] = {'ctx': index, 'value': 0, 'prevValue': -1};
});
var canvasKeys = Object.keys(info);
info.days.denominator = time.day;
info.hours.denominator = time.hour;
info.minutes.denominator = time.minute;
info.seconds.denominator = time.second;
// show remaining time
function showRemainingTime() {
var now = new Date();
// calculate new values
var secondsLeft = Math.max(0, Math.floor((endCountdown - now)/1000));
info.days.value = Math.floor(secondsLeft / (time.second*time.minute*time.hour));
info.hours.value = Math.floor((secondsLeft % (time.second*time.minute*time.hour)) / (time.second*time.minute));
info.minutes.value = Math.floor((secondsLeft % (time.second*time.minute)) / time.second);
info.seconds.value = Math.floor(secondsLeft % time.second);
// update changed values only
canvasKeys.forEach( function(key) {
if(info[key].value !== info[key].prevValue){
if(key === 'days' && info[key].value > 365) {
// exception if days is more than 1 year
draw(canvasCtx[info[key].ctx], 1, key, info[key].value);
} else {
draw(canvasCtx[info[key].ctx], info[key].value/info[key].denominator, key, info[key].value);
}
info[key].prevValue = info[key].value;
}
});
}
// draw function
function draw(ctx, part, id, value) {
// calculate angles
var start = specs.offset;
var between = 2 * Math.PI * part + specs.offset;
var end = 2 * Math.PI + specs.offset;
// clear canvas
ctx.clearRect(0, 0, specs.centerX * 2, specs.centerY * 2);
// draw remaining %
ctx.fillStyle = specs.color;
ctx.beginPath();
ctx.arc(specs.centerX, specs.centerY, specs.radius, start, between);
ctx.arc(specs.centerX, specs.centerY, specs.radius - specs.thickness, between, start, true);
ctx.closePath();
ctx.fill();
// draw bg
ctx.fillStyle = specs.bgColor;
ctx.beginPath();
ctx.arc(specs.centerX, specs.centerY, specs.radius, between, end);
ctx.arc(specs.centerX, specs.centerY, specs.radius - specs.thickness, end, between, true);
ctx.closePath();
ctx.fill();
// draw text
ctx.fillStyle = specs.fontColor;
ctx.font = specs.idFont;
ctx.fillText(id, specs.radius - ctx.measureText(id).width/2, specs.thickness*3);
ctx.font = specs.valueFont;
ctx.fillText(value, specs.radius - ctx.measureText(value).width/2, specs.radius*2 - specs.thickness*3);
}
// change countdown every second
timer = setInterval(showRemainingTime, 1000);
So that this question does not go unanswered, the solution is to make the radius, centerX, and centerY values in the code sample (and codepen) larger.

kineticjs show image anchors on click

I have a kineticjs canvas with image upload and text input, both functions are working fine but I can't get the image resize anchors to show... I need to get the image resize anchors to show "onClick" of the image.
any help is much appreciated :)
thanks in advance.
here is the js
var stage = new Kinetic.Stage({
container: 'container',
width: 375,
height: 200
});
var layer = new Kinetic.Layer();
//image loader
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var img = new Image();
img.onload = function(){
layer.add(new Kinetic.Image({
x: 100,
y: 50,
image: img,
width: 200,
height: 130,
draggable: true
}));
text.moveToTop();
stage.draw();
};
console.log(event);
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
// parameters
var resizerRadius = 3;
var rr = resizerRadius * resizerRadius;
// constant
var pi2 = Math.PI * 2;
function draw(img, withAnchors, withBorders) {
// clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw the image
var view = img.view;
ctx.drawImage(img, 0, 0, img.width, img.height, view.left, view.top, view.width, view.height);
// optionally draw the draggable anchors
if (withAnchors) {
drawDragAnchor(view.left, view.top);
drawDragAnchor(view.left + view.width, view.top);
drawDragAnchor(view.left + view.width, view.top + view.height);
drawDragAnchor(view.left, view.top + view.height);
}
// optionally draw the connecting anchor lines
if (withBorders) {
ctx.beginPath();
ctx.rect(view.left, view.top, view.width, view.height);
ctx.stroke();
}
drawText();
}
function drawDragAnchor(x, y) {
ctx.beginPath();
ctx.arc(x, y, resizerRadius, 0, pi2, false);
ctx.closePath();
ctx.fill();
}
function drawText(){
var x = 40,
y = 100;
ctx.font = "bold 20px sans-serif";
ctx.fillStyle = "black";
ctx.fillText($("#textBox").val(), x, y);
}
// -------------------------------------------
// - Hit Testing -
// -------------------------------------------
// return 0,1,2, or 3 if (x,y) hits the respective anchor
// of the given view.
// return -1 if no anchor hit.
function anchorHitTest(view, x, y) {
var dx, dy;
x -= view.left;
y -= view.top;
// top-left
dx = x;
dy = y;
if (dx * dx + dy * dy <= rr) return (0);
// top-right
dx = x - view.width;
dy = y;
if (dx * dx + dy * dy <= rr) return (1);
// bottom-right
dx = x - view.width;
dy = y - view.height;
if (dx * dx + dy * dy <= rr) return (2);
// bottom-left
dx = x;
dy = y - view.height;
if (dx * dx + dy * dy <= rr) return (3);
return (-1);
}
// return true if (x,y) lies within the view
function hitImage(view, x, y) {
x -= view.left;
y -= view.top;
return (x > 0 && x < view.width && y > 0 && y < view.height);
}
// -------------------------------------------
// - Mouse -
// -------------------------------------------
var mousePos = {
x: 0,
y: 0
};
var draggingImage = false;
var startX, startY;
var isDown = false;
var currentImg = null;
var draggingResizer;
function updateMousePos(e) {
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
updateMousePos = function (e) {
mousePos.x = parseInt(e.clientX - offsetX);
mousePos.y = parseInt(e.clientY - offsetY);
};
return updateMousePos(e);
}
function handleMouseDown(e) {
updateMousePos(e);
// here you could make a loop to see which image / anchor was clicked
draggingResizer = anchorHitTest(img.view, mousePos.x, mousePos.y);
draggingImage = draggingResizer < 0 && hitImage(img.view, mousePos.x, mousePos.y);
//
if (draggingResizer<0 && !draggingImage) return;
startX = mousePos.x;
startY = mousePos.y;
currentImg = img;
}
function handleMouseUp(e) {
if (!currentImg) return;
draggingResizer = -1;
draggingImage = false;
draw(currentImg, true, false);
currentImg = null;
}
function handleMouseOut(e) {
handleMouseUp(e);
}
function handleMouseMove(e) {
if (!currentImg) return;
updateMousePos(e);
var view = currentImg.view;
if (draggingResizer > -1) {
var oldView = {
left: view.left,
top: view.top,
width: view.width,
height: view.height
};
// resize the image
switch (draggingResizer) {
case 0:
cl('ttoo');
//top-left
view.left = mousePos.x;
view.top = mousePos.y;
view.width = oldView.left + oldView.width - mousePos.x;
view.height = oldView.top + oldView.height - mousePos.y;
break;
case 1:
//top-right
// view.left unchanged
view.top = mousePos.y;
view.width = mousePos.x - oldView.left;
view.height = oldView.top + oldView.height - mousePos.y;
break;
case 2:
//bottom-right
view.width = mousePos.x - oldView.left;
view.height = mousePos.y - oldView.top;
break;
case 3:
//bottom-left
view.left = mousePos.x;
view.width = oldView.left + oldView.width - mousePos.x;
view.height = mousePos.y - (oldView.top);
break;
}
if (view.width < 25) view.width = 25;
if (view.height < 25) view.height = 25;
// redraw the image with resizing anchors
draw(currentImg, true, true);
} else if (draggingImage) {
imageClick = false;
// move the image by the amount of the latest drag
var dx = mousePos.x - startX;
var dy = mousePos.y - startY;
view.left += dx;
view.top += dy;
// reset the startXY for next time
startX = mousePos.x;
startY = mousePos.y;
// redraw the image with border
draw(currentImg, false, true);
}
}
var text = new Kinetic.Text({
x: 20,
y: 30,
text: '',
fontSize: '30',
fontFamily: 'Calibri',
fill: 'black',
draggable: true
});
stage.add(layer);
layer.add(text);
document.getElementById("textBox").addEventListener("keyup", function () {
text.setText(this.value);
layer.draw();
}, true);
document.getElementById("textSize").addEventListener("change", function () {
var size = this.value;
text.fontSize(size);
layer.draw();
}, true);
document.getElementById("fontFamily").addEventListener("change", function () {
var font = this.value;
text.fontFamily(font);
layer.draw();
}, true);
document.getElementById("fontStyle").addEventListener("change", function () {
var style = this.value;
text.fontStyle(style);
layer.draw();
}, true);
document.getElementById("fill").addEventListener("change", function () {
var colour = this.value;
text.fill(colour);
layer.draw();
}, true);
$("#canvas").mousedown(function (e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function (e) {
handleMouseMove(e);
});
$("#canvas").mouseup(function (e) {
handleMouseUp(e);
});
$("#canvas").mouseout(function (e) {
handleMouseOut(e);
});
// utility
function cl() {
console.log.apply(console, arguments);
}
can provide jsFiddle if needed :)
You're trying to mix KineticJS with html canvas drawing commands.
That combination doesn't work because KineticJS does its magic by taking over the canvas--leaving no ability to call native canvas commands like context.beginPath.
// these 2 don't play together
... new Kinetic.Image ...
... ctx.beginPath ...
Anyway, Here's the answer to your question (in case you choose KineticJS for your project)
Kinetic.Image can be asked to execute a function when the image is clicked like this:
var image=new Kinetic.Image({
x: 100,
y: 50,
image: img,
width: 200,
height: 130,
draggable: true
}));
image.on("click",function(){
// The image was clicked
// Show your anchors now
});
layer.add(image);
[ Addition: Example of Kinetic.Image resizing ]
I don't like the overhead and complexity of maintaining anchors to resize Kinetic.Images.
Here's an example that lets you drag on the right side of the image to scale it proportionally:
http://jsfiddle.net/m1erickson/p8bpC/
You could modify this code to add cosmetic resizing grabbers (the grabbers are not necessary, but if you prefer the "anchor" look, you can add them).
You can refer to this question, the answers are guided and constructive, and contain a jsfiddle with the exact same behavior that you need.
Kinetic JS - how do you hide all the anchors for a given group ID

how to set google map icon color change per second

i have set red text marker , but i want to show obviously,
how to change marker color per second (for example like red and blue change per second )?
Is this possible?
function createMarkerIcon(text, opt) {
var defaultOptions =
{
fontStyle: "normal", //normal, bold, italic
fontName: "Arival",
fontSize: 12,
bgColor: "#999999",
fgColor: "white",
padding: 4,
arrowHeight: 6
};
options = $.extend(defaultOptions, opt);
var canvas = document.createElement("canvas"),
context = canvas.getContext("2d");
var font = options.fontStyle + " " + options.fontSize + "px " +
options.fontName;
context.font = font;
var metrics = context.measureText(text);
var w = metrics.width + options.padding * 2;
var h = options.fontSize + options.padding * 2 +options.arrowHeight;
canvas.width = w;
canvas.height = h;
context.beginPath();
context.rect(0, 0, w, h - options.arrowHeight);
context.fillStyle = options.bgColor;
context.fill();
context.beginPath();
var x = w / 2, y = h, arwSz = options.arrowHeight;
context.moveTo(x, y);
context.lineTo(x - arwSz, y - arwSz);
context.lineTo(x + arwSz, y - arwSz);
context.lineTo(x, y);
context.fill();
context.textAlign = "center";
context.fillStyle = options.fgColor;
context.font = font;
context.fillText(text,
w / 2,
(h - options.arrowHeight) / 2 + options.padding);
return canvas.toDataURL();
}
marker = new google.maps.Marker({
position: lat,
map: map,
content: redloc[j][1],
title: addressDetails[5],
icon: createMarkerIcon(addressDetails[3], {
bgColor:"#FF0000" })
//icon: "http://labs.google.com/ridefinder/images/mm_20_green.png"
});
Any help will be greatly appreciated!?
andrew
Marker objects have setIcon() method which can be used to change the icon of the marker. If you want to change icon every x seconds, then you must call setIcon() in setInterval() function:
var color = "red";
setInterval(function() {
if(color === "blue") {
// set color red
marker.setIcon(createMarkerIcon("some text", {
bgColor:"#FF0000" }));
// If you have multiple markers, uncomment below and comment above
/*for(var i = 0; i < markerArray.length; i++) {
markerArray[i].setIcon("http://labs.google.com/ridefinder/images/mm_20_red.png");
}*/
color = "red";
} else {
// set color blue
marker.setIcon(createMarkerIcon("some text again", {
bgColor:"#0900FF" }));
// If you have multiple markers, uncomment below and comment above
/*for(var i = 0; i < markerArray.length; i++) {
markerArray[i].setIcon("http://labs.google.com/ridefinder/images/mm_20_red.png");
}*/
color = "blue";
}
}, 1000 ); // every 1 second
You should add this after you define marker (or if you have multiple markers, add after you push created markers to marker array). Note that I used your createMarkerIcon() as parameter for setIcon().
DEMO -- UPDATED FOR MULTIPLE MARKERS

Kinect JS cropping rectangle

I am already using jQuery plugin called jCrop but recently I discovered KinectJs and it really solves many problems for me. Then I stumbled upon this example:
http://www.html5canvastutorials.com/labs/html5-canvas-drag-and-drop-resize-and-invert-images/
And I decided to write my own cropping rectangle based on KinectJs and above example.
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var cropper = group.get('.cropper')[0];
var leftMask = group.getParent().get('.leftMask')[0];
var rightMask = group.getParent().get('.rightMask')[0];
var topMask = group.getParent().get('.topMask')[0];
var bottomMask = group.getParent().get('.bottomMask')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
updateLeftMaskWidth(leftMask,activeAnchor);
updateTopMaskHeight(topMask,cropper,activeAnchor);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
updateRightMaskWidthAndPos(rightMask,activeAnchor);
updateTopMaskHeight(topMask,cropper,activeAnchor);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
updateRightMaskWidthAndPos(rightMask,activeAnchor);
updateBottomMaskHeightAndPos(bottomMask,cropper,activeAnchor);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
updateLeftMaskWidth(leftMask,activeAnchor);
updateBottomMaskHeightAndPos(bottomMask,cropper,activeAnchor);
break;
}
cropper.setPosition(topLeft.getPosition().x,topLeft.getPosition().y);
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if(width && height) {
cropper.setSize(width, height);
}
}
function updateLeftMaskWidth(mask,leftAnchor) {
mask.setWidth(leftAnchor.getAbsolutePosition().x - 100);
}
function updateRightMaskWidthAndPos(mask,rightAnchor) {
mask.setAbsolutePosition(rightAnchor.getAbsolutePosition().x,mask.getAbsolutePosition().y);
mask.setWidth(213 - (rightAnchor.getAbsolutePosition().x - 100));
}
function updateTopMaskHeight(mask,cropper,topAnchor) {
mask.setAbsolutePosition(topAnchor.getAbsolutePosition().x,mask.getAbsolutePosition().y);
mask.setHeight(topAnchor.getAbsolutePosition().y - 110);
mask.setWidth(cropper.getWidth());
}
function updateBottomMaskHeightAndPos(mask,cropper,bottomAnchor) {
mask.setAbsolutePosition(bottomAnchor.getAbsolutePosition().x, bottomAnchor.getAbsolutePosition().y);
mask.setHeight(236 - (bottomAnchor.getAbsolutePosition().y - 110));
mask.setWidth(cropper.getWidth());
}
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 1,
radius: 5,
name: name,
draggable: true,
dragBoundFunc: function(pos) {
var newX = pos.x;
var newY = pos.y;
var image = this.getParent().getParent().get('.image')[0];
var cropper = this.getParent();
// Bound horizontally
if(newX < 100) {
newX = 100;
}
else if(newX > image.getWidth() + 100 - cropper.getWidth()) {
newX = image.getWidth() + 100 - cropper.getWidth();
}
if(newY < 110) {
newY = 110;
}
else if(newY > image.getHeight() + 110 - cropper.getHeight()) {
newY = image.getHeight() + 110 - cropper.getHeight();
}
return {
x: newX,
y: newY
}
}
});
anchor.on('dragmove', function() {
update(this);
layer.draw();
});
// add hover styling
anchor.on('mouseover', function() {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(2);
layer.draw();
});
anchor.on('mouseout', function() {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
function initStage(img) {
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 400
});
var imageGroup = new Kinetic.Group({
x: 100,
y: 110
});
var leftMaskGroup = new Kinetic.Group({
x: 100,
y: 110
});
var rightMaskGroup = new Kinetic.Group({
x: 270,
y: 110
});
var topMaskGroup = new Kinetic.Group({
x: 169.9,
y: 110
});
var bottomMaskGroup = new Kinetic.Group({
x: 169.9,
y: 150+138
});
var cropperGroup = new Kinetic.Group({
x: 170,
y: 150,
draggable: true,
dragBoundFunc: function(pos) {
var newX = pos.x;
var newY = pos.y;
var image = this.getParent().get('.image')[0];
var cropper = this.get('.cropper')[0];
// Bound horizontally
if(newX < 100) {
newX = 100;
}
else if(newX > image.getWidth() + 100 - cropper.getWidth()) {
newX = image.getWidth() + 100 - cropper.getWidth();
}
// Bound vertically
if(newY < 110) {
newY = 110;
}
else if(newY > image.getHeight() + 110 - cropper.getHeight()) {
newY = image.getHeight() + 110 - cropper.getHeight();
}
return {
x: newX,
y: newY
}
}
});
var layer = new Kinetic.Layer();
/*
* go ahead and add the groups
* to the layer and the layer to the
* stage so that the groups have knowledge
* of its layer and stage
*/
layer.add(imageGroup);
layer.add(leftMaskGroup);
layer.add(rightMaskGroup);
layer.add(topMaskGroup);
layer.add(bottomMaskGroup);
layer.add(cropperGroup);
stage.add(layer);
// cropping rectangle
var cropperRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 100,
height: 138,
stroke: 'black',
name: 'cropper',
strokeWidth: 1
});
cropperGroup.add(cropperRect);
addAnchor(cropperGroup, 0, 0, 'topLeft');
addAnchor(cropperGroup, 100, 0, 'topRight');
addAnchor(cropperGroup, 100, 138, 'bottomRight');
addAnchor(cropperGroup, 0, 138, 'bottomLeft');
cropperGroup.on('dragstart', function() {
this.moveToTop();
});
cropperGroup.on('dragmove', function() {
var layer = this.getLayer();
var topLeft = this.get('.topLeft')[0];
var bottomLeft = this.get('.bottomLeft')[0];
var topRight = this.get('.topRight')[0];
var leftMask = this.getParent().get('.leftMask')[0];
var rightMask = this.getParent().get('.rightMask')[0];
var topMask = this.getParent().get('.topMask')[0];
var bottomMask = this.getParent().get('.bottomMask')[0];
updateLeftMaskWidth(leftMask,topLeft);
updateRightMaskWidthAndPos(rightMask,topRight);
updateTopMaskHeight(topMask,this.get('.cropper')[0],topLeft);
updateBottomMaskHeightAndPos(bottomMask,this.get('.cropper')[0],bottomLeft);
layer.draw();
});
// left mask
var leftMaskRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 70,
height: 236,
fill: 'black',
name: 'leftMask',
strokeWidth: 0,
opacity: 0.5
});
leftMaskGroup.add(leftMaskRect);
// right mask
var rightMaskRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 213-170,
height: 236,
fill: 'black',
name: 'rightMask',
strokeWidth: 0,
opacity: 0.5
});
rightMaskGroup.add(rightMaskRect);
// top mask
var topMaskRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 100.2,
height: 150-110,
fill: 'black',
name: 'topMask',
strokeWidth: 0,
opacity: 0.5
});
topMaskGroup.add(topMaskRect);
// bottom mask
var bottomMaskRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 100.2,
height: 236-138-(150-110),
fill: 'black',
name: 'bottomMask',
strokeWidth: 0,
opacity: 0.5
});
bottomMaskGroup.add(bottomMaskRect);
// image
var srcImg = new Kinetic.Image({
x: 0,
y: 0,
image: img,
name: 'image'
});
imageGroup.add(srcImg);
stage.draw();
}
var img = new Image();
img.onload = function() {
initStage(this);
}
img.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
It works almost perfectly. The problem is that when you resize using the circle anchors and after a few tries (just give it a few shots) when you try to drag the whole rectangle it allows you to drag it out of bounds !
From my debugging this seems like an issue with the library but if sb. sees the problem in my code or sees a way to optimize it please share your thoughts.
The result of my effort can be seen here:
http://jsfiddle.net/wanderer/WLpXF/
A) Reproducing the bug:
Drag a top anchor upwards (say it was dragged N pixels)
Drag the entire cropper upwards; it can leave the image boundaries by N pixels
Similar behaviour for the other anchors and directions.
B) The solution:
Add this function to the script:
function readjust() {
var group = this.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var cropper = group.get('.cropper')[0];
var tlx = cropper.getX(),
tly = cropper.getY(),
w = cropper.getWidth(),
h = cropper.getHeight();
group.setX(group.getX() + tlx);
group.setY(group.getY() + tly);
topLeft.setPosition(0,0);
topRight.setPosition(w,0);
bottomLeft.setPosition(0,h);
bottomRight.setPosition(w,h);
cropper.setPosition(0,0);
}
And the following handler in addAnchor():
anchor.on('dragend', readjust);
Fiddle: http://jsfiddle.net/BMy7b/1/
Alternatively the code from readjust() can be included in update(), as suggested by MarmiK. This would run more operations on every drag thus might be slower (but I am not sure; opinions?). Fiddle: http://jsfiddle.net/vUPeQ/1/
The problem was that the cropper and anchors moved relatively to the cropperGroup, but the cropperGroup drag bounding function wasn't taking it into account.
Have fun!
One quick update: I was after something like this (nice looking cropping rectangle), but when I try this code with the latest KineticJS 5.0.1, well, it does a couple of nasty things. You can see by yourselves here: [http://jsfiddle.net/vUPeQ/2/]:http://jsfiddle.net/vUPeQ/2/
My wild guess is that it's because some api changes, but I can't find which one...
Can anyone give a hand over here?
Thanks so much!!!