Here is my current project code:
size(500,500);
background(255, 255, 255);
fill(250,0,0);
ellipse(150, 230, 100, 200);
fill(10,0,0);
ellipse(180, 233, 30, 30);
fill(10,0,0);
ellipse(120, 233, 30, 30);
fill(250,250,250);
ellipse(120,233,10,20);
fill(250,250,250);
ellipse(180,233,10,20);
arc(150, 280, 60, 90, 0, PI/1);
fill(250,0,0);
rect(100,330,100,100);
fill(10,10,10);
rect(50,330,50,50);
fill(10,10,10);
rect(200,330,50,50);
fill(250,0,0);
rect(90,430,50,100);
fill(250,0,0);
rect(160,430,50,100);
fill(10,0,0);
triangle(60, 300, 101, 10, 50, 450);
Could someone please provide code on how to draw a basic 5 pointed star beside the deadpool character? (within the sized 500,500 dimensions)
See the processing documentation of PShapes where there is a very simple implementation of a star shape in the Custom PShapes section.
See the p5.js example which is very similar.
The code can be used in processing.js, too. You have to change createCanvas(500,500) to size(500,500) and push() respectively pop() to pushMatrix() respectively popMatrix():
function setup() {
createCanvas(500,500);
}
function draw() {
background(255, 255, 255);
// star
push();
translate(280, 290); // center of the star
fill(102);
beginShape();
vertex(0, -50);
vertex(14, -20);
vertex(47, -15);
vertex(23, 7);
vertex(29, 40);
vertex(0, 25);
vertex(-29, 40);
vertex(-23, 7);
vertex(-47, -15);
vertex(-14, -20);
endShape(CLOSE);
translate(100, 100);
pop();
// character
fill(250,0,0);
ellipse(150, 230, 100, 200);
fill(10,0,0);
ellipse(180, 233, 30, 30);
fill(10,0,0);
ellipse(120, 233, 30, 30);
fill(250,250,250);
ellipse(120,233,10,20);
fill(250,250,250);
ellipse(180,233,10,20);
arc(150, 280, 60, 90, 0, PI/1);
fill(250,0,0);
rect(100,330,100,100);
fill(10,10,10);
rect(50,330,50,50);
fill(10,10,10);
rect(200,330,50,50);
fill(250,0,0);
rect(90,430,50,100);
fill(250,0,0);
rect(160,430,50,100);
fill(10,0,0);
triangle(60, 300, 101, 10, 50, 450);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>
Related
Is there any way to add an image into chart area [I'm using chart JS bubble chart].
Presently I added image to canvas through css.
Best approach, drawing it on the canvas
The best way to achieve this is by drawing it directly on the canvas since you have direct access and control over the pixels so you are sure it is aligned pixel perfect.
Extending on uminders answer, but making it so it only draws within the chart area:
const myChart = new Chart('myChart', {
type: 'bubble',
plugins: [{
beforeDraw: chart => {
var ctx = chart.ctx;
ctx.save();
const image = new Image();
image.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Stack_Overflow_logo.svg/2560px-Stack_Overflow_logo.svg.png';
ctx.drawImage(image, chart.chartArea.left, chart.chartArea.top, chart.chartArea.width, chart.chartArea.height);
ctx.restore();
}
}],
data: {
datasets: [{
label: 'My Dataset',
data: [{
x: 0,
y: 12,
r: 10
},
{
x: 1,
y: 19,
r: 12
},
{
x: 2,
y: 3,
r: 8
},
{
x: 3,
y: 5,
r: 7
},
{
x: 4,
y: 2,
r: 4
},
{
x: 5,
y: 3,
r: 8
}
],
backgroundColor: [
'rgba(255, 99, 132, 0.4)',
'rgba(54, 162, 235, 0.4)',
'rgba(255, 206, 86, 0.4)',
'rgba(75, 192, 192, 0.4)',
'rgba(153, 102, 255, 0.4)',
'rgba(255, 159, 64, 0.4)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
]
}]
},
options: {
responsive: true,
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.js"></script>
<canvas id="myChart" height="80"></canvas>
Alternative approach without drawing on the canvas
If you really don't want to draw it on the canvas but use a normal img element, you can use an absolute position and use a custom plugin to position it correctly, downside is that it seems that canvas pixels are different from CSS so they cant be used 1:1 and have to be approximated which may lead to slight alignment issues:
const myChart = new Chart('myChart', {
type: 'bubble',
plugins: [{
beforeDraw: chart => {
const image = document.getElementById('img')
image.width = chart.chartArea.width;
image.height = chart.chartArea.height;
image.style.left = `${chart.chartArea.left*1.3}px`;
image.style.top = `${chart.chartArea.top*1.3}px`;
}
}],
data: {
datasets: [{
label: 'My Dataset',
data: [{
x: 0,
y: 12,
r: 10
},
{
x: 1,
y: 19,
r: 12
},
{
x: 2,
y: 3,
r: 8
},
{
x: 3,
y: 5,
r: 7
},
{
x: 4,
y: 2,
r: 4
},
{
x: 5,
y: 3,
r: 8
}
],
backgroundColor: [
'rgba(255, 99, 132, 0.4)',
'rgba(54, 162, 235, 0.4)',
'rgba(255, 206, 86, 0.4)',
'rgba(75, 192, 192, 0.4)',
'rgba(153, 102, 255, 0.4)',
'rgba(255, 159, 64, 0.4)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
]
}]
},
options: {
responsive: true,
}
});
#img {
position: absolute;
z-index: -1/* Draw image behind the canvas */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.js"></script>
<img id="img" src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Stack_Overflow_logo.svg/2560px-Stack_Overflow_logo.svg.png" />
<canvas id="myChart" height="80"></canvas>
The Plugin Core API offers a range of hooks that can be used for performing custom code. You can use the beforeDraw for example to draw the images through CanvasRenderingContext2D.drawImage(). But this effectively draws the image directly on the canvas.
plugins: [{
beforeDraw: chart => {
var ctx = chart.chart.ctx;
ctx.save();
var image = new Image();
image.src = 'https://i.stack.imgur.com/S7tJH.png';
imageSize = 250;
ctx.drawImage(image, chart.chart.width / 2 - imageSize / 2, chart.chart.height / 2 - imageSize / 2, imageSize, imageSize);
ctx.restore();
}
}],
Please have a look at the runnable code snippet below.
var myChart = new Chart('myChart', {
type: 'bubble',
plugins: [{
beforeDraw: chart => {
var ctx = chart.chart.ctx;
ctx.save();
var image = new Image();
image.src = 'https://i.stack.imgur.com/S7tJH.png';
imageSize = 250;
ctx.drawImage(image, chart.chart.width / 2 - imageSize / 2, chart.chart.height / 2 - imageSize / 2, imageSize, imageSize);
ctx.restore();
}
}],
data: {
datasets: [{
label: 'My Dataset',
data: [
{ x: "05:22", y: 12, r: 10 },
{ x: "12:13", y: 19, r: 12 },
{ x: "13:45", y: 3, r: 8 },
{ x: "18:31", y: 5, r: 7 },
{ x: "19:05", y: 2, r: 4 },
{ x: "22:55", y: 3, r: 8 }
],
backgroundColor: [
'rgba(255, 99, 132, 0.4)',
'rgba(54, 162, 235, 0.4)',
'rgba(255, 206, 86, 0.4)',
'rgba(75, 192, 192, 0.4)',
'rgba(153, 102, 255, 0.4)',
'rgba(255, 159, 64, 0.4)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
]
}]
},
options: {
responsive: true,
legend: {
display: false
},
scales: {
xAxes: [{
type: 'time',
time: {
parser: 'HH:mm',
unit: 'hour',
stepSize: 1,
displayFormats: {
hour: 'HH:mm'
},
tooltipFormat: 'HH:mm'
},
ticks: {
min: '00:00',
max: '24:00',
callback: (value, index) => index == 24 ? '24:00' : value
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 5
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart" height="80"></canvas>
I am new to D3.Js, I found below example of sunburst with line chart, I was able to use it.
http://bl.ocks.org/wizicer/raw/f662a0b04425fc0f7489/
jsfiddle:Link
However, it displays only year values in X axis, but I need custom text labels such as "March 2019", April 2019" etc.
Default X axis
Is it possible to replace year values(1999, 2000, 2001 etc) as shown below with text labels?
var chart = {},
rect = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
g = 500 - rect.left - rect.right,
h = 400 - rect.top - rect.bottom,
i = [1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013],
j = d3.scale.linear().range([0, g]),
k = d3.scale.linear().range([h, 0]),
bottomtick = d3
.svg
.axis()
.scale(j)
.tickValues([1999, 2004, 2009, 2013])
.tickFormat(d3.format(".0f"))
.tickPadding(10)
.tickSize(0)
.orient("bottom"),
Format of the source data
var skillsdata;
skillsdata = {
"Skills": {
"Server & WinForm": {
"Protocol": {
"Propose": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 30, 50, 50, 50],
"USSD": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 50, 40, 30],
"UAP": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 70, 50, 30],
"Socket Raw": [0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 50, 50, 50, 70, 80]
},
My edit
var chart = {},
rect = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
g = 500 - rect.left - rect.right,
h = 400 - rect.top - rect.bottom,
j = d3.time.scale().domain([new Date("2014-01-01"), new Date("2016-06-01")]).range([0, 850]),
k = d3.scale.linear().range([h, 0]),
bottomtick = d3
.svg
.axis()
.scale(j)
.tickFormat(d3.time.format("%B %Y"))
.tickPadding(10)
.tickSize(0)
.orient("bottom"),
lefttick = d3
.svg
.axis()
.scale(k)
.tickSize(0)
.tickPadding(10)
.tickValues([20, 40, 60, 80, 100])
.orient("left"),
The timeformats available in d3.v3 is defined here in this document: https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md.
I have attached a snippet to show how we can achieve it, hope this is helpful! I believe you just have to do:
// tick-format:
.tickFormat(d3.time.format("%B %Y"))
//scale type
d3.time.scale()
var svg = d3.select("body")
.append("svg")
.attr("width", 900)
.attr("height", 100)
var xScale = d3.time.scale()
.domain([new Date("2014-01-01"), new Date("2016-01-01")])
.range([0, 850]);
var xAxis = d3.svg.axis()
.scale(xScale)
.tickFormat(d3.time.format("%B %Y"))
.orient("bottom");
svg.append("g").call(xAxis);
<script src="https://d3js.org/d3.v3.min.js"></script>
PFont mono;
float x;
float y;
float speed;
int m=millis();
void setup() {
size(720, 480);
background(0);
mono = createFont("Helvetica", 100);
textFont(mono);
text("Ê", 90, 270);
text("X", 190, 270);
text("T", 295, 270);
text("A", 385, 270);
text("S", 480, 270);
text("E", 580, 270);
}
void draw() {
speed+=1.5;
if (260-speed<250) {
speed*=-1;
}
if (mouseX>85 && 95<mouseX && mouseY>220 && 320>mouseY) {
background(0);
fill(random(255), random(255), random(255));
text("Ê", 90+random(-10, 10), 270-speed);
fill(255);
text("X", 190, 270);
text("T", 295, 270);
text("A", 385, 270);
text("S", 480, 270);
text("E", 580, 270);
}
if (mouseX>185 && 195<mouseX && mouseY>220 && 320>mouseY) {
background(0);
fill(random(255), random(255), random(255));
text("X", 190+random(-10, 10), 270-speed);
fill(255);
text("Ê", 90, 270);
text("T", 295, 270);
text("A", 385, 270);
text("S", 480, 270);
text("E", 580, 270);
}
if (mouseX>290 && 300<mouseX && mouseY>220 && 320>mouseY) {
background(0);
fill(random(255), random(255), random(255));
text("T", 295+random(-10, 10), 270-speed);
fill(255);
text("Ê", 90, 270);
text("X", 190, 270);
text("A", 385, 270);
text("S", 480, 270);
text("E", 580, 270);
}
if (mouseX>380 && 390<mouseX && mouseY>220 && 320>mouseY) {
background(0);
fill(random(255), random(255), random(255));
text("A", 385+random(-10, 10), 270-speed);
fill(255);
text("S", 480, 270);
text("E", 580, 270);
text("Ê", 90, 270);
text("X", 190, 270);
text("T", 295, 270);
}
if (mouseX>475 && 480<mouseX && mouseY>220 && 320>mouseY) {
background(0);
fill(random(255), random(255), random(255));
text("S", 480+random(-10, 10), 270-speed);
fill(255);
text("E", 580, 270);
text("Ê", 90, 270);
text("X", 190, 270);
text("T", 295, 270);
text("A", 385, 270);
}
if (mouseX>575 && 585<mouseX && mouseY>220 && 320>mouseY) {
background(0);
fill(random(255), random(255), random(255));
text("E", 580+random(-10, 10), 270-speed);
fill(255);
text("Ê", 90, 270);
text("X", 190, 270);
text("T", 295, 270);
text("A", 385, 270);
text("S", 480, 270);
}
}
This is my code and i want to make it so that when the mouse has left a certain position it keeps doing the cicle for 5 seconds, and that after that it returns to the position that is the setup.
Thanks in advance
You're thinking about it a little bit backwards: you don't want to stay inside the if statement for 5 seconds. Instead, you want the if statement to evaluate to true for 5 seconds.
This might sound like nit-picking, but the big difference is that you want this to stay true between calls to the draw() function.
You can do that using a boolean variable, an int variable, and the millis() function.
Step 1: Use a boolean variable to keep track of whether you should be doing the thing. Set this to true when you want to start doing the thing.
Step 2: Use an int variable to keep track of when you started doing the thing. Set this to millis() when you start doing the thing.
Step 3: In your draw() function, check the boolean variable to decide whether to do the thing. If it's true, do the thing.
Step 4: Also in your draw() function, check the int variable against the current value of millis() to decide if enough time has elapsed. If so, set the boolean back to false.
Here's a small example that shows a circle for 5 seconds whenever the user clicks:
float circleX;
float circleY;
boolean showCircle = false;
int startTime;
void setup() {
size(500, 500);
}
void draw() {
if (millis() > startTime + 5*1000) {
showCircle = false;
}
if (mousePressed) {
circleX = mouseX;
circleY = mouseY;
startTime = millis();
showCircle = true;
}
background(0);
if (showCircle) {
ellipse(circleX, circleY, 100, 100);
}
}
If you still have questions, please work from an MCVE like this instead of posting your entire project.
In my application I have several shapes that intersect with each other, for example, Shape A, Shape B and Shape C. A need to draw a polyline from Shape A to Shape C through Shape B, so the line lies inside all the shapes and crosses them almost at center.
What is the most efficient way to implement this? Here is the code of example: http://jsfiddle.net/dselkirk/ZMUkE/.
I need to draw a yellow line, but not manually:
var stage = new Kinetic.Stage({
container: 'container',
width: 850,
height: 750
});
var layer = new Kinetic.Layer({
x: 0,
y: 0
});
var rect = new Kinetic.Rect({
x: 100,
y: 100,
width: 80,
height: 60,
fill: '#E67E22'
});
var rect2 = new Kinetic.Rect({
x: 640,
y: 70,
width: 40,
height: 70,
fill: '#3498DB',
});
var circle = new Kinetic.Circle({
x: 600,
y: 150,
radius: 70,
fill: '#2ECC71',
});
var polyOne = new Kinetic.Polygon({
x: 80,
y: 100,
points: [73, 192, 73, 160, 340, 23, 500, 109, 499, 139, 342, 93],
fill: '#9B59B6'
});
var polyTwo = new Kinetic.Polygon({
x: 100,
y: 160,
points: [-5, 0, 75, 0, 70, 10, 70, 60, 60, 90, 61, 92, 64, 96, 66, 100, 67, 105, 67, 110, 67, 113, 66, 117, 64, 120, 63, 122, 61, 124, 58, 127, 55, 129, 53, 130, 50, 130, 20, 130, 17, 130, 15, 129, 12, 127, 9, 124, 7, 122, 6, 120, 4, 117, 3, 113, 3, 110, 3, 105, 4, 100, 6, 96, 9, 92, 10, 90, 0, 60, 0, 10],
fill: '#e74c3c'
});
var imageObj = new Image();
imageObj.onload = function () {
var yoda = new Kinetic.Image({
x: 120,
y: 120,
image: imageObj,
width: 15,
height: 18
});
// add the shape to the layer
layer.add(yoda);
stage.add(layer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
var imageObj2 = new Image();
imageObj2.onload = function () {
var dart = new Kinetic.Image({
x: 650,
y: 80,
image: imageObj2,
width: 20,
height: 21
});
layer.add(dart);
stage.add(layer);
};
var yellowLine = new Kinetic.Line({
points: [{x:125,y:140},{x:125,y:280}, {x:425,y:150}, {x:555,y:220}, {x:655,y:100}],
stroke: 'yellow',
strokeWidth: 2,
lineJoin: 'round',
dashArray: [33, 10]
});
layer.add(polyOne);
layer.add(polyTwo);
layer.add(yellowLine);
layer.add(circle);
layer.add(rect);
layer.add(rect2);
stage.add(layer);
yellowLine.moveToTop();
For now I think the algorithm should be:
1) Find intersection points of all shapes.
2) Draw lines between these intersectiopn points. If any line point lies outside the shape - move it horizontally/vertically till it lies inside the shape.
But this algorithm seems not efficient at all.
I am creating an app which support all orientation.
I am using navigationController here.
for orientation i am using this code
- (void)willAnimateRotationToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
if (interfaceOrientation == UIInterfaceOrientationPortrait
|| interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
category1.frame = CGRectMake(54, 68, 190, 174);
category2.frame = CGRectMake(291, 68, 190, 174);
category3.frame = CGRectMake(525, 68, 190, 174);
category4.frame = CGRectMake(54, 296, 190, 174);
category5.frame = CGRectMake(291, 296, 190, 174);
category6.frame = CGRectMake(525, 296, 190, 174);
category7.frame = CGRectMake(54, 527, 190, 174);
category8.frame = CGRectMake(291, 527, 190, 174);
category9.frame = CGRectMake(525, 527, 190, 174);
category10.frame = CGRectMake(291, 757, 190, 174);
extra1.frame = CGRectMake(80, 781, 138, 125);
extra2.frame = CGRectMake(551, 781, 138, 125);
}
else
{
category1.frame = CGRectMake(61, 50, 190, 174);
category2.frame = CGRectMake(298, 50, 190, 174);
category3.frame = CGRectMake(537, 50, 190, 174);
category4.frame = CGRectMake(774, 50, 190, 174);
category5.frame = CGRectMake(61, 278, 190, 174);
category6.frame = CGRectMake(298, 278, 190, 174);
category7.frame = CGRectMake(537, 278, 190, 174);
category8.frame = CGRectMake(774, 278, 190, 174);
category9.frame = CGRectMake(298, 509, 190, 174);
category10.frame = CGRectMake(537, 509, 190, 174);
extra1.frame = CGRectMake(80, 533, 120, 125);
extra2.frame = CGRectMake(800, 533, 120, 125);
}
}
It works perfectly in this view. when i tab button it goes to secondviewcontroller where i am showing tableview.
But , if i go back to the firstview via navigation back button ,the orientation is not showing perfectly.
Above code is not working for navigation back button.
What should i do for this problem??
Any suggestion ??
Thank you in advance.
Edited:
I have removed my above function from firstview and copy the code to this function.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait
|| interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
category1.frame = CGRectMake(54, 68, 190, 174);
category2.frame = CGRectMake(291, 68, 190, 174);
category3.frame = CGRectMake(525, 68, 190, 174);
category4.frame = CGRectMake(54, 296, 190, 174);
category5.frame = CGRectMake(291, 296, 190, 174);
category6.frame = CGRectMake(525, 296, 190, 174);
category7.frame = CGRectMake(54, 527, 190, 174);
category8.frame = CGRectMake(291, 527, 190, 174);
category9.frame = CGRectMake(525, 527, 190, 174);
category10.frame = CGRectMake(291, 757, 190, 174);
extra1.frame = CGRectMake(80, 781, 138, 125);
extra2.frame = CGRectMake(551, 781, 138, 125);
}
else
{
category1.frame = CGRectMake(61, 50, 190, 174);
category2.frame = CGRectMake(298, 50, 190, 174);
category3.frame = CGRectMake(537, 50, 190, 174);
category4.frame = CGRectMake(774, 50, 190, 174);
category5.frame = CGRectMake(61, 278, 190, 174);
category6.frame = CGRectMake(298, 278, 190, 174);
category7.frame = CGRectMake(537, 278, 190, 174);
category8.frame = CGRectMake(774, 278, 190, 174);
category9.frame = CGRectMake(298, 509, 190, 174);
category10.frame = CGRectMake(537, 509, 190, 174);
extra1.frame = CGRectMake(80, 533, 120, 125);
extra2.frame = CGRectMake(800, 533, 120, 125);
}
return YES;
}
in my second view controller i have done
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
When i go back to the firstview by tapping navigation back button else condition(landscape mode) works fine but i don't know why it is not working with if condition(Portraitmode).
Write all this code in the following function.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//set all the frames according to the current interface orientation
return YES;
}
NEW EDIT :
Write this method into your detailviewcontroller.m file
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
UIViewController *controller = [self.navigationController.viewControllers objectAtIndex:0];
[controller shouldAutorotateToInterfaceOrientation:interfaceOrientation];
return YES;
}