在 p5js 中绘制箭头

Drawing Arrows in p5js

我碰巧在大学从事图论可视化项目。对于这个项目,我们不能使用任何处理图形存储和算法的现有库(所以我不能使用 D3 或 python 的 NetworkX 之类的东西)。这个项目更多的是关于算法的可视化(BFS、DFS、Dijkstra、着色等),所以我选择 JavaScript 使用 p5js 作为我的可视化辅助工具。

我面临的问题是我试图在顶点之间绘制箭头,但结果并不像预期的那样:

编辑 1

更改了问题以符合 mod 的评论。

这是 sketch.js 展示我是如何让它发挥作用的:

var x1; //starting vertex
var x2; //ending vertex
var r = 16; //vertex radius


function setup() {
    createCanvas(640, 480);
    x1 = createVector(random(0, width/2), random(0, height/2)); //random position to the upper left
    x2 = createVector(random(width/2, width), random(height/2, height)); //random position to the lower right
}

function draw() {
    background(200);
    stroke(0);
    var offset = r;
    ellipse(x1.x, x1.y, r, r); //starting vertex
    ellipse(x2.x, x2.y, r, r); //ending vertex
    line(x1.x, x1.y, x2.x, x2.y); //draw a line beetween the vertices

    // this code is to make the arrow point
    push() //start new drawing state
    var angle = atan2(x1.y - x2.y, x1.x - x2.x); //gets the angle of the line
    translate(x2.x, x2.y); //translates to the destination vertex
    rotate(angle); //rotates the arrow point
    triangle(-offset*0.5, offset, offset*0.5, offset, 0, -offset/2); //draws the arrow point as a triangle
    pop();
}

感谢您的帮助。 :)

将旋转设置为 0 时,箭头指向上方,而旋转 0 时箭头应指向右侧。一种选择是绘制箭头,使尖端默认指向东方,否则您可以简单地将角度偏移 -90 度(-HALF_PI 弧度):

// this code is to make the arrow point
    push() //start new drawing state
    var angle = atan2(x1.y - x2.y, x1.x - x2.x); //gets the angle of the line
    translate(x2.x, x2.y); //translates to the destination vertex
    rotate(angle-HALF_PI); //rotates the arrow point
    triangle(-offset*0.5, offset, offset*0.5, offset, 0, -offset/2); //draws the arrow point as a triangle
    pop();

查看:

var x1; //starting vertex
var x2; //ending vertex
var r = 16; //vertex radius


function setup() {
    createCanvas(640, 480);
    x1 = createVector(random(0, width/2), random(0, height/2)); //random position to the upper left
    x2 = createVector(random(width/2, width), random(height/2, height)); //random position to the lower right
}

function draw() {
    background(200);
    stroke(0);
    var offset = r;
    ellipse(x1.x, x1.y, r, r); //starting vertex
    ellipse(x2.x, x2.y, r, r); //ending vertex
    line(x1.x, x1.y, x2.x, x2.y); //draw a line beetween the vertices

    // this code is to make the arrow point
    push() //start new drawing state
    var angle = atan2(x1.y - x2.y, x1.x - x2.x); //gets the angle of the line
    translate(x2.x, x2.y); //translates to the destination vertex
    rotate(angle-HALF_PI); //rotates the arrow point
    triangle(-offset*0.5, offset, offset*0.5, offset, 0, -offset/2); //draws the arrow point as a triangle
    pop();
    
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>

箭头函数:

function setup() {
  createCanvas(windowWidth,windowHeight);
  cursor(ARROW);
  colorMode(HSL, 100);
}

function arrow(x,y,x2,y2,length,xs, ys, rotat, style, plan, xshadow, yshadow,txt){
  if (x == undefined) {
    x = 0;
  }
 if (y == undefined) {
    y = 0;
  }
  if (x == undefined) {
    x2 = 0;
  }
 if (y == undefined) {
    y2 = 0;
  }
  if (ys == undefined) {
    ys = 3;
  } else if (ys == '0') {
    ys = 0.0001;
  }
  if (xs == undefined) {
    xs = 5;
  } else if (xs == '0') {
    xs = 0.0001;
  }
  if (length == undefined) {
    length = 5;
  }
 var angle = atan2(y2-y, x2-x);
  if (rotat != undefined) { // write undefined without '' in the call to skip the rotating mode
    ys = ys*sin(frameCount/10);
  }
  var rxs = constrain(xs,0.0001,9);
  push();
  translate(x,y);
  rotate(angle);
  strokeJoin(ROUND);
  beginShape()
  if (plan == undefined || plan == '2D' || plan == '2d' || plan == '') {
  if (style == 'large') {
  vertex(0,-ys/1.5*length);
  } else if (style == 'pointy') {
  vertex(0,0);
  } else if (style == 'indication') {
  vertex(0,-ys*length);
  } else {
  vertex(0,-ys/3*length);
  }
  if (style == 'indication') {
  vertex(rxs*length, -ys*length);
  } else {
  vertex(rxs*length, -ys/3*length);
  }
  vertex(rxs*length, -ys*length);
  vertex(9*length, 0);
  vertex(rxs*length, ys*length);
  if (style == 'indication') {
  vertex(rxs*length, ys*length);
  } else {
  vertex(rxs*length, ys/3*length);
  }
  if (style == 'large') {
  vertex(0,ys/1.5*length);
  } else if (style == 'pointy') {
  vertex(0,0);
  } else if (style == 'indication') {
  vertex(0,ys*length);
  } else {
  vertex(0,ys/3*length);
  }
  } else if (plan == '3D' || plan == '3d') {
 var nl = false;
 if (length < 0) {
 length = abs(length);
 rotate(radians(180))
 nl = true;
 }
  var shadowx = 0;
  var shadowy = 0;
  if (xshadow != 0 || xshadow != undefined) {
  shadowx = length*xshadow;
  }
 if (xshadow == 0 || xshadow == undefined) {
  shadowx = 0.0001
  }
  if (yshadow != 0 || yshadow != undefined) {
  shadowy = length*yshadow;
  }
 if (yshadow == 0 || yshadow == undefined) {
  shadowy = 0.0001
  }
 if (nl == true) {
  shadowx = -shadowx
  shadowy = -shadowy
 }
  var yp = 0;
  if (style == 'large') {
  yp = ys/1.5*length;
  } else if (style == 'pointy') {
  yp = 0;
  } else if (style == 'indication') {
  yp = ys*length;
  } else {
  yp = ys/3*length;
  }
  var yq = 0;
  if (style == 'indication') {
  yq = ys*length;
  } else {
  yq = ys/3*length;
  }
  if (rotat != undefined) { // write undefined without '' in the call to skip the rotating mode
    shadowy = (abs(shadowy)+abs(shadowx))*sin(7.854+frameCount/10);
    shadowx = 0.01
    if (ys > 0) {
  vertex(0,-yp);
  vertex(rxs*length, -yq);
  vertex(rxs*length, -ys*length);
  vertex(9*length, 0);
  vertex(rxs*length, ys*length);
  vertex(rxs*length, yq);
  vertex(0,yp);
    } else {
  vertex(0+shadowx,-yp+shadowy);
  vertex(rxs*length+shadowx, -yq+shadowy);
  vertex(rxs*length+shadowx, -ys*length+shadowy);
  vertex(9*length+shadowx, 0+shadowy);
  vertex(rxs*length+shadowx, ys*length+shadowy);
  vertex(rxs*length+shadowx, yq+shadowy);
  vertex(0+shadowx,yp+shadowy);
    }
  }
 translate(-shadowx/2 ,-shadowy/2)
  if (rotat == undefined) {
  if (ys < 0) {
  if (shadowx > 0 && shadowy > 0){
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  } else if (shadowx < 0 && shadowy > 0){
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  quad(rxs*length+shadowx,-yq+shadowy,rxs*length, -yq,rxs*length, -ys*length,shadowx+rxs*length,-ys*length+shadowy)
  quad(rxs*length+shadowx,yq+shadowy,rxs*length, yq,rxs*length, ys*length,shadowx+rxs*length,ys*length+shadowy)
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(shadowx,-yp+shadowy,0,-yp,0,yp,shadowx,yp+shadowy)
  } else if (shadowx < 0 && shadowy < 0){
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  quad(rxs*length+shadowx,-yq+shadowy,rxs*length, -yq,rxs*length, -ys*length,shadowx+rxs*length,-ys*length+shadowy)
  quad(rxs*length+shadowx,yq+shadowy,rxs*length, yq,rxs*length, ys*length,shadowx+rxs*length,ys*length+shadowy)
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(shadowx,-yp+shadowy,0,-yp,0,yp,shadowx,yp+shadowy)
  } else if (shadowx > 0 && shadowy < 0){
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  }
  } else if (ys > 0) {
  if (shadowx > 0 && shadowy > 0){
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  } else if (shadowx < 0 && shadowy > 0){
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  quad(rxs*length+shadowx,-yq+shadowy,rxs*length, -yq,rxs*length, -ys*length,shadowx+rxs*length,-ys*length+shadowy)
  quad(rxs*length+shadowx,yq+shadowy,rxs*length, yq,rxs*length, ys*length,shadowx+rxs*length,ys*length+shadowy)
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(shadowx,-yp+shadowy,0,-yp,0,yp,shadowx,yp+shadowy)
  } else if (shadowx < 0 && shadowy < 0){
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  quad(rxs*length+shadowx,-yq+shadowy,rxs*length, -yq,rxs*length, -ys*length,shadowx+rxs*length,-ys*length+shadowy)
  quad(rxs*length+shadowx,yq+shadowy,rxs*length, yq,rxs*length, ys*length,shadowx+rxs*length,ys*length+shadowy)
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(shadowx,-yp+shadowy,0,-yp,0,yp,shadowx,yp+shadowy)
  } else if (shadowx > 0 && shadowy < 0){
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  }
  }
  vertex(0,-yp);
  vertex(rxs*length, -yq);
  vertex(rxs*length, -ys*length);
  vertex(9*length, 0);
  vertex(rxs*length, ys*length);
  vertex(rxs*length, yq);
  vertex(0,yp);
  } else {
  if (shadowx > 0 && shadowy > 0){
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  } else if (shadowx < 0 && shadowy > 0){
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  quad(rxs*length+shadowx,-yq+shadowy,rxs*length, -yq,rxs*length, -ys*length,shadowx+rxs*length,-ys*length+shadowy)
  quad(rxs*length+shadowx,yq+shadowy,rxs*length, yq,rxs*length, ys*length,shadowx+rxs*length,ys*length+shadowy)
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(shadowx,-yp+shadowy,0,-yp,0,yp,shadowx,yp+shadowy)
  } else if (shadowx < 0 && shadowy < 0){
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  quad(rxs*length+shadowx,-yq+shadowy,rxs*length, -yq,rxs*length, -ys*length,shadowx+rxs*length,-ys*length+shadowy)
  quad(rxs*length+shadowx,yq+shadowy,rxs*length, yq,rxs*length, ys*length,shadowx+rxs*length,ys*length+shadowy)
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(shadowx,-yp+shadowy,0,-yp,0,yp,shadowx,yp+shadowy)
  } else if (shadowx > 0 && shadowy < 0){
  quad(0,yp,rxs*length,yq,shadowx+rxs*length,yq+shadowy,shadowx,yp+shadowy)
  quad(0,-yp,rxs*length,-yq,shadowx+rxs*length,-yq+shadowy,shadowx,-yp+shadowy)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, ys*length+shadowy,rxs*length, ys*length)
  quad(9*length,0,9*length+shadowx,0+shadowy,rxs*length+shadowx, -ys*length+shadowy,rxs*length, -ys*length)
  }
  }
  }
  endShape(CLOSE);
 fill(0)
 if (plan == undefined || plan == '2D' || plan == '2d' || plan == ''){
 if (txt != undefined && style != 'pointy') {
    textAlign(CENTER, CENTER);
  textSize(constrain(Math.min((abs(length)*100)/textWidth(txt)*0.95,abs(ys*abs(length)/1.5)),0.000001,Infinity))
  text(txt,4.5*length,0);
 }
 if (txt != undefined && style == 'pointy') {
    textAlign(CENTER, CENTER);
  textSize(constrain(Math.min(abs(length)*75/textWidth(txt)*(Math.min(abs(9*length)-rxs*abs(length)+0.01,constrain(rxs*abs(length),(6*abs(length))-rxs*abs(length)+0.01,rxs*abs(length)))*0.5/(abs(length)*2))*0.95,abs(ys*abs(length)/1.5)*0.80),0.000001,Infinity))
  text(txt,4.5*length,0);
 }
 } else if (plan == '3D' || plan == '3d') {
 if (rotat != undefined) {
 if (ys > 0) {
 if (nl == true) {
 translate(4.5*length,0)
 rotate(radians(180))
 translate(-4.5*length,-0)
 }
 if (txt != undefined && style != 'pointy') {
    textAlign(CENTER, CENTER);
  textSize(constrain(Math.min((abs(length)*100)/textWidth(txt)*0.95,abs(ys*abs(length)/1.5)),0.000001,Infinity))
  text(txt,4.5*length,0);
 }
 if (txt != undefined && style == 'pointy') {
    textAlign(CENTER, CENTER);
  textSize(constrain(Math.min(abs(length)*75/textWidth(txt)*(Math.min(abs(9*length)-rxs*abs(length)+0.01,constrain(rxs*abs(length),(6*abs(length))-rxs*abs(length)+0.01,rxs*abs(length)))*0.5/(abs(length)*2))*0.95,abs(ys*abs(length)/1.5)*0.80),0.000001,Infinity))
  text(txt,4.5*length,0);
 }
 } else {
 if (nl == true) {
 translate(4.5*length,(-yq+shadowy+yq+shadowy)/2)
 rotate(radians(180))
 translate(-4.5*length,-(-yq+shadowy+yq+shadowy)/2)
 }
 if (txt != undefined && style != 'pointy') {
    textAlign(CENTER, CENTER);
  textSize(constrain(Math.min((abs(length)*100)/textWidth(txt)*0.95,abs(ys*abs(length)/1.5)),0.000001,Infinity))
  text(txt,4.5*length,(-yq+shadowy+yq+shadowy)/2);
 }
 if (txt != undefined && style == 'pointy') {
    textAlign(CENTER, CENTER);
  textSize(constrain(Math.min(abs(length)*75/textWidth(txt)*(Math.min(abs(9*length)-rxs*abs(length)+0.01,constrain(rxs*abs(length),(6*abs(length))-rxs*abs(length)+0.01,rxs*abs(length)))*0.5/(abs(length)*2))*0.95,abs(ys*abs(length)/1.5)*0.80),0.000001,Infinity))
  text(txt,4.5*length,(-yq+shadowy+yq+shadowy)/2);
 }
 }
 } else {
 if (nl == true) {
 translate(4.5*length,0)
 rotate(radians(180))
 translate(-4.5*length,-0)
 }
 if (txt != undefined && style != 'pointy') {
    textAlign(CENTER, CENTER);
  textSize(constrain(Math.min((abs(length)*100)/textWidth(txt)*0.95,abs(ys*abs(length)/1.5)),0.000001,Infinity))
  text(txt,4.5*length,0);
 }
 if (txt != undefined && style == 'pointy') {
    textAlign(CENTER, CENTER);
  textSize(constrain(Math.min(abs(length)*75/textWidth(txt)*(Math.min(abs(9*length)-rxs*abs(length)+0.01,constrain(rxs*abs(length),(6*abs(length))-rxs*abs(length)+0.01,rxs*abs(length)))*0.5/(abs(length)*2))*0.95,abs(ys*abs(length)/1.5)*0.80),0.000001,Infinity))
  text(txt,4.5*length,0);
 }
 }
 }
  pop();
}

function draw() {
  var wwidth = 710;
  var wheight = 522;
  background(255);
  fill('#ffd480');
  ellipse(wwidth/2,wheight/2,100)
  fill(0);
  var angle = 0;
  var x = 0;
  var y = 0;
  for (var a = 0; a < 360; a+=6) {
    angle = radians(a);
    x = wwidth/2 + cos(angle) * 48;
    y = wheight/2 + sin(angle) * 48;
    line(x,y,wwidth/2,wheight/2)
  }
  fill('#ffd480')
  noStroke();
  ellipse(wwidth/2,wheight/2,85)
  stroke(0);
  fill(0);
  textAlign(CENTER, CENTER);
  angle = radians(90);
  x = wwidth/2 + cos(angle) * 35;
  y = wheight/2 + sin(angle) * 35;
  text('S',x,y)
  angle = radians(180);
  x = wwidth/2 + cos(angle) * 35;
  y = wheight/2 + sin(angle) * 35;
  text('W',x,y)
  angle = radians(270);
  x = wwidth/2 + cos(angle) * 35;
  y = wheight/2 + sin(angle) * 35;
  text('N',x,y)
  angle = radians(360);
  x = wwidth/2 + cos(angle) * 35;
  y = wheight/2 + sin(angle) * 35;
  text('E',x,y)
  for(var i=0; i<2; i++){
    for(var j=0; j<2; j++){
      fill(IncrClrVal(100,0.5,0,1,(i+j)*10), 100, 50);
      arrow(30+20*i,30+20*j,mouseX,mouseY,sin(frameCount/100)*2,5,3,'',undefined);
      fill(IncrClrVal(100,0.5,0,1,(i+2+j)*10), 100, 50);
      arrow(70+20*i,30+20*j,mouseX,mouseY,sin(frameCount/100)*2,5,3,undefined,'indication');
      fill(IncrClrVal(100,0.5,0,1,(i+j+2)*10), 100, 50);
      arrow(30+20*i,70+20*j,mouseX,mouseY,sin(frameCount/100)*2,5,3,undefined,'large');
      fill(IncrClrVal(100,0.5,0,1,(i+2+j+2)*10), 100, 50);
      arrow(70+20*i,70+20*j,mouseX,mouseY,sin(frameCount/100)*2,5,3,undefined,'pointy');
      fill(IncrClrVal(100,0.5,0,1,(i+4+j)*10), 100, 50);
      arrow(110+20*i,30+20*j,mouseX,mouseY,sin(frameCount/100)*2,5,3,'rotate',undefined,'3D',3,1);
      fill(IncrClrVal(100,0.5,0,1,(i+6+j)*10), 100, 50);
      arrow(150+20*i,30+20*j,mouseX,mouseY,sin(frameCount/100)*2,5,3,undefined,'indication','3D',3,1,'Hey!');
      fill(IncrClrVal(100,0.5,0,1,(i+4+j+2)*10), 100, 50);
      arrow(110+20*i,70+20*j,mouseX,mouseY,sin(frameCount/100)*2,5,3,undefined,'large','3D',3,1);
      fill(IncrClrVal(100,0.5,0,1,(i+6+j+2)*10), 100, 50);
      arrow(150+20*i,70+20*j,mouseX,mouseY,sin(frameCount/100)*2,5,3,undefined,'pointy','3D',3,1);
    }
  }
 push();
 var jitter = 0;
  if (Math.round(second()) % 2 === 0 && IncrClrVal(10,-0.1)-1.5 > 0 && IncrClrVal(10,0.1)-1.5 > 0) {
    jitter = random(-0.2, 0.2);
  } else {
  if (Math.round(Date.now()/7500)%2 === 0 && IncrClrVal(10,-0.1)-1.5 != IncrClrVal(10,0.1)-1.5) {
  jitter = IncrClrVal(10,-0.1)-1.5;
  } else if (Math.round(second()) % 2 != 0) {
  jitter = IncrClrVal(10,0.1)-1.5;
  }
 }
  x = cos(jitter) * wwidth;
  y = sin(jitter) * wheight;
  fill(5,100,50);
  arrow(wwidth/2, wheight/2, x, y,-5,undefined,undefined,undefined,undefined,undefined,undefined,undefined,'SOUTH')
  fill(60,100,50);
  arrow(wwidth/2, wheight/2, x, y,5,undefined,undefined,undefined,undefined,undefined,undefined,undefined,'NORTH')
 pop();
  fill(0);
 translate(-pmouseX+wwidth/2,-pmouseY+wheight/2)
  arrow(pmouseX, pmouseY, mouseX, mouseY,3,5,3/2);
 translate(pmouseX-wwidth/2,pmouseY-wheight/2)
  fill(80);
  arrow(wwidth/2, wheight/2, mouseX, mouseY,3,5,3/2);
 fill(50);
 ellipse(wwidth/2,wheight/2,8)
 var styles = ['normal','large','pointy','indication'];
  fill(IncrClrVal(100,0.5), 100, 50);
  arrow(270, 50,undefined,undefined,10)
  arrow(370, 50,undefined,undefined,10,undefined,undefined,undefined,'indication')
  arrow(470, 50,undefined,undefined,10,undefined,undefined,undefined,'large')
  arrow(570, 50,undefined,undefined,10,undefined,undefined,undefined,'pointy')
  arrow(270, 120,undefined,undefined,10,undefined,undefined,'rotate')
  arrow(370, 120,undefined,undefined,10,undefined,undefined,'rotate','indication')
  arrow(470, 120,undefined,undefined,10,undefined,undefined,'rotate','large')
  arrow(570, 120,undefined,undefined,10,undefined,undefined,'rotate','pointy')
 var xperspectiv = constrain(map(mouseX,30,240,0,2),0,2);
 var yperspectiv = constrain(map(mouseY,120,250,0,1),0,1);
  arrow(30, 150,undefined,undefined,10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.0005,0,0,0))],'3D',-xperspectiv,-yperspectiv)
  arrow(150, 150,undefined,undefined,10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.0005,0,0,1))],'3D',xperspectiv,-yperspectiv)
  arrow(30, 220,undefined,undefined,10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.0005,0,0,2))],'3D',-xperspectiv,yperspectiv)
  arrow(150, 220,undefined,undefined,10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.0005,0,0,3))],'3D',xperspectiv,yperspectiv)
  arrow(30, 300,undefined,undefined,10,undefined,undefined,'rotate',styles[Math.floor(IncrClrVal(4,0.0005,0,0,0))],'3D',-xperspectiv,-yperspectiv)
  arrow(150, 300,undefined,undefined,10,undefined,undefined,'rotate',styles[Math.floor(IncrClrVal(4,0.0005,0,0,1))],'3D',xperspectiv,-yperspectiv)
  arrow(30, 370,undefined,undefined,10,undefined,undefined,'rotate',styles[Math.floor(IncrClrVal(4,0.0005,0,0,2))],'3D',-xperspectiv,yperspectiv)
  arrow(150, 370,undefined,undefined,10,undefined,undefined,'rotate',styles[Math.floor(IncrClrVal(4,0.0005,0,0,3))],'3D',xperspectiv,yperspectiv)
 arrow(470,190,undefined,undefined,10,undefined,undefined,'rotate',styles[Math.floor(IncrClrVal(4,0.0005))],undefined,undefined,undefined,'SOME TEXT')
 arrow(570,190,undefined,undefined,10,undefined,undefined,'rotate',styles[Math.floor(IncrClrVal(4,0.0005))],'3d',1,1,'SOME TEXT')
 arrow(470+10*9,260,undefined,undefined,-10,undefined,undefined,'rotate',styles[Math.floor(IncrClrVal(4,0.0005))],'2d',undefined,undefined,'REVERSED')
 arrow(570+10*9,260,undefined,undefined,-10,undefined,undefined,'rotate',styles[Math.floor(IncrClrVal(4,0.0005))],'3d',1,1,'REVERSED')
 if (mouseX < 660 && mouseX > 570 && mouseY < 360 && mouseY > 300) {
  var xs1 = (mouseX-570)/10;
  var ys1 = (mouseY-330)/10;
 }
 arrow(570,330,undefined,undefined,10,xs1,ys1,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'3d',1,1,'RESIZE ME!')
 if (mouseX < 560 && mouseX > 470 && mouseY < 360 && mouseY > 300) {
  var xs2 = (mouseX-470)/10;
  var ys2 = (mouseY-330)/10;
 }
 arrow(470,330,undefined,undefined,10,xs2,ys2,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'2d',undefined,undefined,'RESIZE ME!')
 if (mouseX < 660 && mouseX > 570 && mouseY < 430 && mouseY > 370) {
  var xs3 = (wwidth-mouseX-(wwidth-660))/10;
  var ys3 = (wheight-mouseY-(wheight-400))/10;
 }
 arrow(570+90,400,undefined,undefined,-10,xs3,ys3,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'3d',1,1,'RESIZE ME!')
 if (mouseX < 560 && mouseX > 470 && mouseY < 430 && mouseY > 370) {
  var xs4 = (wwidth-mouseX-(wwidth-560))/10;
  var ys4 = (wheight-mouseY-(wheight-400))/10;
 }
 arrow(470+90,400,undefined,undefined,-10,xs4,ys4,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'2d',undefined,undefined,'RESIZE ME!')
 if (mouseX > 570 && mouseX < 660 && mouseY > 440 && mouseY < 500) {
 arrow(615-(constrain(mouseX,570,660)-570-90/2),470,mouseX,undefined,(constrain(mouseX,570,660)-570-90/2)/4.5,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'3d',1,1,'REVERSE ME!')
 } else if (mouseX < 615) {
 arrow(660,470,mouseX,undefined,-10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'3d',1,1,'REVERSE ME!')
 } else {
 arrow(570,470,mouseX,undefined,10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'3d',1,1,'REVERSE ME!')
 }
 if (mouseX > 470 && mouseX < 560 && mouseY > 440 && mouseY < 500) {
 arrow(515-(constrain(mouseX,470,560)-470-90/2),470,undefined,undefined,(constrain(mouseX,470,560)-470-90/2)/4.5,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'2d',undefined,undefined,'REVERSE ME!')
 } else if (mouseX < 515) {
 arrow(560,470,undefined,undefined,-10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'2d',undefined,undefined,'REVERSE ME!')
 } else {
 arrow(470,470,undefined,undefined,10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.005))],'2d',undefined,undefined,'REVERSE ME!')
 }
 if (mouseX > 160 && mouseX < 560 && mouseY > 275 && mouseY < 595) {
 arrow(310,400,undefined,undefined,10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.005,0,0,2))],'3d',(wwidth-355-constrain(mouseX,305,405))/5,(-wheight-constrain(mouseY+35,405,465)+435+wheight)/5,'HOVER ME!')
 } else {
 arrow(310,400,undefined,undefined,10,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,0.005,0,0,2))],'2d',undefined,undefined,'HOVER ME!')
 }
 var demo = ['H','Hi','Hi ','Hi t','Hi th','Hi the','Hi ther','Hi there','Hi there!','Hi there!','Hi there!','Hi there!','Hi there!','W','We','Wel','Welc','Welco','Welcom','Welcome','Welcome ','Welcome t','Welcome to','Welcome to ','Welcome to t','Welcome to th','Welcome to the','Welcome to the ','Welcome to the a','Welcome to the ar','Welcome to the arr','Welcome to the arro','Welcome to the arrow','Welcome to the arrow ','Welcome to the arrow p','Welcome to the arrow pa','Welcome to the arrow par','Welcome to the arrow part','Welcome to the arrow party','Welcome to the arrow party!','Welcome to the arrow party!','Welcome to the arrow party!','Welcome to the arrow party!','Welcome to the arrow party!','Y','Yo','You','You ','You c','You ca','You can','You can ','You can t','You can ti','You can tic','You can tick','You can tickl','You can tickle','a','an','any','any ','any o','any of','any of ','any of m','any of my','any of my ','any of my f','any of my fr','any of my fri','any of my frie','any of my frien','any of my friend','any of my friends','a','an','and','and ','and s','and se','and see','and see ','and see i','and see if','and see if ','and see if t','and see if th','and see if the','and see if they','and see if they ','and see if they r','and see if they re','and see if they res','and see if they resp','and see if they respo','and see if they respon','and see if they respond','and see if they respond!','and see if they respond!','and see if they respond!','and see if they respond!','and see if they respond!','A','Al','Als','Also','Also ','Also I','Also I ','Also I c','Also I ca','Also I can','Also I can ','Also I can m','Also I can ma','Also I can mak','Also I can make','Also I can make ','Also I can make v','Also I can make ve','Also I can make ver','Also I can make very','Also I can make very ','Also I can make very v','Also I can make very ve','Also I can make very ver','Also I can make very very','Also I can make very very ','Also I can make very very v','Also I can make very very ve','Also I can make very very ver','Also I can make very very very','Also I can make very very very ','Also I can make very very very v','Also I can make very very very ve','Also I can make very very very ver','Also I can make very very very very','Also I can make very very very very ','Also I can make very very very very v','Also I can make very very very very ve','Also I can make very very very very ver','Also I can make very very very very very','Also I can make very very very very very ','Also I can make very very very very very v','Also I can make very very very very very ve','Also I can make very very very very very ver','Also I can make very very very very very very','Also I can make very very very very very very ','Also I can make very very very very very very l','Also I can make very very very very very very lo','Also I can make very very very very very very lon','Also I can make very very very very very very long','Also I can make very very very very very very long ','Also I can make very very very very very very long s','Also I can make very very very very very very long se','Also I can make very very very very very very long sen','Also I can make very very very very very very long sent','Also I can make very very very very very very long sente','Also I can make very very very very very very long senten','Also I can make very very very very very very long sentenc','Also I can make very very very very very very long sentence','Also I can make very very very very very very long sentences','Also I can make very very very very very very long sentences!','Also I can make very very very very very very long sentences!','Also I can make very very very very very very long sentences!','Also I can make very very very very very very long sentences!','Also I can make very very very very very very long sentences!']
 x = 142.5+cos(radians(IncrClrVal(360,2))) * 100;
  y = 460+sin(radians(IncrClrVal(360,2))) * 100;
  arrow(75, 460,undefined,undefined,15,undefined,undefined,undefined,styles[Math.floor(IncrClrVal(4,1/1670,0,0,0))],'3D',(wwidth-(wwidth-142.5)-x)/60,(wheight-(wheight-460)-y)/60,demo[Math.floor(IncrClrVal(167,0.1))])
 fill(0,100,50)
 arrow(135,240,135,340,5,undefined,undefined,undefined,undefined,undefined,undefined,undefined,'ROTATING')
 if (mouseX > 305 && mouseX < 405 && mouseY > 370 && mouseY < 430) {
 noCursor();
 push();
 translate(mouseX,mouseY)
 fill(0)
 stroke(85)
 fill(85)
 strokeWeight(1.5);
 rotate(radians(-10)+atan2(mouseY-400, mouseX-355))
 arrow(-18, -4, 0, 0,2,3,2.5);
 rotate(radians(10))
 stroke(100)
 fill(0)
 strokeWeight(1);
 arrow(-17, 0, 0, 0,2,3,2.5);
 pop();
 } else if (mouseX > 20 && mouseY > 20) {
 noCursor();
 push();
 strokeWeight(1.5);
 translate(mouseX,mouseY)
 rotate(radians(248))
  if (dist(mouseX, mouseY, wwidth/2, wheight/2) < 50) {
 stroke(85)
 fill(85)
 strokeWeight(1.5);
 rotate(radians(-10))
 arrow(-18, -4, 0, 0,2,3,2.5,'');
 rotate(radians(10))
 stroke(100)
 fill(0)
 strokeWeight(1);
 arrow(-17, 0, 0, 0,2,3,2.5,'');
 } else {
 stroke(85)
 fill(85)
 strokeWeight(1.5);
 rotate(radians(-10))
 arrow(-18, -4, 0, 0,2,3,2.5);
 rotate(radians(10))
 stroke(100)
 fill(0)
 strokeWeight(1);
 arrow(-17, 0, 0, 0,2,3,2.5);
 }
 rotate(radians(-248))
 pop();
 } else {
 cursor(ARROW);
 }
}



// Don't pay attention to these
function getDec(value) {
  return value % 1 ? value.toString().split(".")[1].length : 0;
}

function IncrClrVal(max,speed,dclg,sens,startdclg) {
  if (max == undefined) {
  max = 100; // 100 = max de données avant de reprendre à 0
  }
  if (speed == undefined || 0) {
  speed = 1; // 1 = 1 par seconde, si speed = undefined alors speed = le slideur 'rbaspeed' 
  }
  if (dclg == undefined) {
  dclg = 0; // décale toutes les valeurs en affectant le maximum ateint
  }
  if (sens == undefined || sens == '0') {
  sens = 1; // -1 --> augmente 1 --> diminu
  }
  if (startdclg == undefined || 0) {
  startdclg = 0; // décalage de départ, décale toutes les valeurs sans affecter le maximum ateint
  }
  return ((Math.sign(sens)*Math.round(Date.now()/(1000/60))*speed+startdclg) - max*Math.floor((Math.sign(sens)*Math.round(Date.now()/(1000/60))*speed+startdclg)/max)+dclg).toFixed(Math.max(getDec(startdclg),getDec(speed),getDec(max),getDec(dclg)));
}


function windowResized() {
    resizeCanvas(windowWidth, windowHeight);
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>