2017-04-24 3 views
-1

Ich benutze Konva-Bibliothek, um etwas Zeug auf HTML5 Canvas zu zeichnen.Canvas senkrechte Punkte auf Linie

var A={x:'',y:''}; 
var B={x:'',y:''}; 
dieses

1) Wie zeichne line:

Ich habe 2 Punkte von Interaktion mit dem Benutzer per Mausklick gegeben? enter image description here

Meine Frage ist:

1) Wie senkrechte Linien auf jedem Intervall zu bekommen?

2) Wie komme ich von A nach B?

3) Wie kommen alle Punkte von A nach B?

4) Wie bekomme ich rote Punkte?

+0

Sie müssen definieren - welche Art von Kurve auf dem Bild ist? Sinus? Senkrecht zu was? Abstand - Länge des geraden Segments oder der Kurvenlänge? – MBo

+0

Es ist Brauch. Alle Entfernungen können abhängig vom Bildschirm flexibel sein. Ich habe nur Punkt A und B. Rote Punkte sind senkrecht von der Linie (A, B), also muss ich diese Punkte finden. –

+0

Gibt es immer die gleiche Anzahl von roten Punkten? Oder kann sich das auch ändern? – MrApnea

Antwort

1

Wir haben die Punkte A und B Differenzvektor

D.X = B.X - A.X 
D.Y = B.Y - A.Y 
Length = Sqrt(D.X * D.X + D.Y * D.Y) 

normalized (unit) vector 
uD.X = D.X/Length 
uD.Y = D.Y/Length 

perpendicular unit vector 
P.X = - uD.Y 
P.Y = uD.X 

some red point: 
R.X = A.X + uD.X * Dist + P.X * SideDist * SideSign  
R.Y = A.Y + uD.Y * Dist + P.Y * SideDist * SideSign   

where Dist is in range 0..Length 
Dist = i/N * Length for N equidistant points 
SideSign is +/- 1 for left and right side 
+0

Danke. Das ist die perfekte Lösung dafür. –

1

Sie haben nicht erklärt, was Ihre Linie ist so gehe ich davon aus es eine Sünde Welle ist (obwohl das Bild wie Kreise zusammengeklebt aussieht ???)

Da MBo die Grundlagen gegeben hat, wird es nur auf die Wellenlinie angewendet.

// normalize a vector 
 
function normalize(vec){ 
 
    var length = Math.sqrt(vec.x * vec.x + vec.y * vec.y); 
 
    vec.x /= length; 
 
    vec.y /= length; 
 
    return vec; 
 
     
 
} 
 
// creates a wavy line 
 
function wavyLine(start, end, waves, amplitude){ 
 
    return ({ 
 
     start, 
 
     end, 
 
     waves, 
 
     amplitude, 
 
     update(){ 
 
      if(this.vec === undefined){ 
 
       this.vec = {}; 
 
       this.norm = {}; 
 
      } 
 
      this.vec.x = this.end.x - this.start.x; 
 
      this.vec.y = this.end.y - this.start.y; 
 
      this.length = Math.sqrt(this.vec.x * this.vec.x + this.vec.y * this.vec.y); 
 
      this.norm.x = this.vec.x/this.length; 
 
      this.norm.y = this.vec.y/this.length; 
 
      return this; 
 
     } 
 
    }).update(); 
 
} 
 

 

 
// draws a wavy line 
 
function drawWavyLine(line) { 
 
    var x, stepSize, i, y, phase, dist; 
 
    ctx.beginPath(); 
 
    stepSize = ctx.lineWidth; 
 
    ctx.moveTo(line.start.x, line.start.y); 
 
    for (i = stepSize; i < line.length; i+= stepSize) { 
 
     x = line.start.x + line.norm.x * i; // get point i pixels from start 
 
     y = line.start.y + line.norm.y * i; // get point i pixels from start 
 
     phase = (i/(line.length/line.waves)) * Math.PI * 2; // get the wave phase at this point 
 
     dist = Math.sin(phase) * line.amplitude; // get the distance from the line to the point on the wavy curve 
 
     x -= line.norm.y * dist; 
 
     y += line.norm.x * dist; 
 
     ctx.lineTo(x, y); 
 
    } 
 
    phase = line.waves * Math.PI * 2; // get the wave phase at this point 
 
    dist = Math.sin(phase) * line.amplitude; // get the distance from the line to the point on the wavy curve 
 
    ctx.lineTo(line.end.x - line.norm.y * dist, line.end.y + line.norm.x * dist);  
 
    ctx.stroke(); 
 
} 
 

 
// find the closest point on a wavy line to a point returns the pos on the wave, tangent and point on the linear line 
 
function closestPointOnLine(point,line){ 
 
    var x = point.x - line.start.x; 
 
    var y = point.y - line.start.y; 
 
    // get the amount the line vec needs to be scaled so tat point is perpendicular to the line 
 
    var l = (line.vec.x * x + line.vec.y * y)/(line.length * line.length); 
 
    x = line.vec.x * l; // scale the vec 
 
    y = line.vec.y * l; 
 
    return pointAtDistance(Math.sqrt(x * x + y * y), line); 
 
} 
 

 

 
// find the point at (linear) distance along wavy line and return coordinate, coordinate on wave, and tangent 
 
function pointAtDistance(distance,line){ 
 
    var lenScale = line.length/line.waves; // scales the length into radians 
 
    var phase = distance * Math.PI * 2/lenScale; // get the wave phase at this point 
 
    var dist = Math.sin(phase) * line.amplitude; // get the distance from the line to the point on the wavy curve 
 
    var slope = Math.cos(phase) * Math.PI * 2 * line.amplitude/lenScale; // derivitive of sin(a*x) is -a*cos(a*x) 
 
    // transform tangent (slope) into a vector along the line. This vector is not a unit vector so normalize it 
 
    var tangent = normalize({ 
 
     x : line.norm.x - line.norm.y * slope, 
 
     y : line.norm.y + line.norm.x * slope 
 
    }); 
 
    // move from the line start to the point on the linear line at distance 
 
    var linear = { 
 
     x : line.start.x + line.norm.x * distance, 
 
     y : line.start.y + line.norm.y * distance 
 
    } 
 
    // move out perpendicular to the wavy part 
 
    return { 
 
     x : linear.x - line.norm.y * dist, 
 
     y : linear.y + line.norm.x * dist, 
 
     tangent,linear 
 
    }; 
 
} 
 

 
// create a wavy line 
 
var wLine = wavyLine({x:10,y:100},{x:300,y:100},3,50); 
 

 

 

 
// draw the wavy line and show some points on it 
 
function display(timer){ 
 
    globalTime = timer; 
 
    ctx.setTransform(1,0,0,1,0,0); // reset transform 
 
    ctx.globalAlpha = 1;   // reset alpha 
 
    ctx.clearRect(0,0,w,h); 
 
    var radius = Math.max(ch,cw); 
 
    // set up the wavy line 
 
    wLine.waves = Math.sin(timer/10000) * 6; 
 
    wLine.start.x = Math.cos(timer/50000) * radius + cw; 
 
    wLine.start.y = Math.sin(timer/50000) * radius + ch; 
 
    wLine.end.x = -Math.cos(timer/50000) * radius + cw; 
 
    wLine.end.y = -Math.sin(timer/50000) * radius + ch ; 
 
    wLine.update(); 
 
    
 
    // draw the linear line 
 
    ctx.lineWidth = 0.5; 
 
    ctx.strokeStyle = "blue"; 
 
    ctx.beginPath(); 
 
    ctx.moveTo(wLine.start.x, wLine.start.y); 
 
    ctx.lineTo(wLine.end.x, wLine.end.y); 
 
    ctx.stroke(); 
 

 
    // draw the wavy line 
 
    ctx.lineWidth = 2; 
 
    ctx.strokeStyle = "black"; 
 
    drawWavyLine(wLine); 
 
    
 
    
 
    // find point nearest mouse 
 
    var p = closestPointOnLine(mouse,wLine); 
 
    ctx.lineWidth = 1; 
 
    ctx.strokeStyle = "red"; 
 
    ctx.beginPath(); 
 
    ctx.arc(p.x,p.y,5,0,Math.PI * 2); 
 
    ctx.moveTo(p.x + p.tangent.x * 20,p.y + p.tangent.y * 20); 
 
    ctx.lineTo(p.x - p.tangent.y * 10,p.y + p.tangent.x * 10); 
 
    ctx.lineTo(p.x + p.tangent.y * 10,p.y - p.tangent.x * 10); 
 
    ctx.closePath(); 
 
    ctx.stroke(); 
 
    
 
    // find points at equal distance along line 
 
    
 
    ctx.lineWidth = 1; 
 
    ctx.strokeStyle = "blue"; 
 
    ctx.beginPath(); 
 
    for(var i = 0; i < w; i += w/10){ 
 
     var p = pointAtDistance(i,wLine); 
 
     ctx.moveTo(p.x + 5,p.y); 
 
     ctx.arc(p.x,p.y,5,0,Math.PI * 2); 
 
     ctx.moveTo(p.x,p.y); 
 
     ctx.lineTo(p.linear.x,p.linear.y); 
 
     ctx.moveTo(p.x + p.tangent.x * 40, p.y + p.tangent.y * 40);   
 
     ctx.lineTo(p.x - p.tangent.x * 40, p.y - p.tangent.y * 40);   
 
     
 
    } 
 
    ctx.stroke(); 
 
    
 
} 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
/****************************************************************************** 
 
The code from here down is generic full page mouse and canvas boiler plate 
 
code. As I do many examples which all require the same mouse and canvas 
 
functionality I have created this code to keep a consistent interface. The 
 
Code may or may not be part of the answer. 
 
This code may or may not have ES6 only sections so will require a transpiler 
 
such as babel.js to run on legacy browsers. 
 
*****************************************************************************/ 
 
// V2.0 ES6 version for Stackoverflow and Groover QuickRun 
 
var w, h, cw, ch, canvas, ctx, mouse, globalTime = 0; 
 
// You can declare onResize (Note the capital R) as a callback that is also 
 
// called once at start up. Warning on first call canvas may not be at full 
 
// size. 
 
;(function(){ 
 
    const RESIZE_DEBOUNCE_TIME = 100; 
 
    var resizeTimeoutHandle; 
 
    var firstRun = true; 
 
    function createCanvas() { 
 
     var c,cs; 
 
     cs = (c = document.createElement("canvas")).style; 
 
     cs.position = "absolute"; 
 
     cs.top = cs.left = "0px"; 
 
     cs.zIndex = 1000; 
 
     document.body.appendChild(c); 
 
     return c; 
 
    } 
 
    function resizeCanvas() { 
 
     if (canvas === undefined) { canvas = createCanvas() } 
 
     canvas.width = innerWidth; 
 
     canvas.height = innerHeight; 
 
     ctx = canvas.getContext("2d"); 
 
     if (typeof setGlobals === "function") { setGlobals() } 
 
     if (typeof onResize === "function") { 
 
      clearTimeout(resizeTimeoutHandle); 
 
      if (firstRun) { onResize() } 
 
      else { resizeTimeoutHandle = setTimeout(onResize, RESIZE_DEBOUNCE_TIME) } 
 
      firstRun = false; 
 
     } 
 
    } 
 
    function setGlobals() { 
 
     cw = (w = canvas.width)/2; 
 
     ch = (h = canvas.height)/2; 
 
    } 
 
    mouse = (function() { 
 
     var m; // alias for mouse 
 
     var mouse = { 
 
      x : 0, y : 0, // mouse position and wheel 
 
      buttonRaw : 0, 
 
      buttonOnMasks : [0b1, 0b10, 0b100], // mouse button on masks 
 
      buttonOffMasks : [0b110, 0b101, 0b011], // mouse button off masks 
 
      bounds : null, 
 
      eventNames : "mousemove,mousedown,mouseup".split(","), 
 
      event(e) { 
 
       var t = e.type; 
 
       m.bounds = m.element.getBoundingClientRect(); 
 
       m.x = e.pageX - m.bounds.left - scrollX; 
 
       m.y = e.pageY - m.bounds.top - scrollY; 
 
       if (t === "mousedown") { m.buttonRaw |= m.buttonOnMasks[e.which - 1] } 
 
       else if (t === "mouseup") { m.buttonRaw &= m.buttonOffMasks[e.which - 1] } 
 
      }, 
 
      start(element) { 
 
       m.element = element === undefined ? document : element; 
 
       m.eventNames.forEach(name => document.addEventListener(name, mouse.event)); 
 
      }, 
 
     } 
 
     m = mouse; 
 
     return mouse; 
 
    })(); 
 

 
    function update(timer) { // Main update loop 
 
     globalTime = timer; 
 
     display(timer);   // call demo code 
 
     requestAnimationFrame(update); 
 
    } 
 
    setTimeout(function(){ 
 
     canvas = createCanvas(); 
 
     mouse.start(canvas); 
 
     resizeCanvas(); 
 
     window.addEventListener("resize", resizeCanvas); 
 
     requestAnimationFrame(update); 
 
    },0); 
 
})();

Verwandte Themen