如何在透明画布上停止线条着色?

时间:2015-05-05 19:13:59

标签: javascript html5 canvas

我需要一些专家帮助。当我使画布背景透明时,该线为整个画布着色(如下面的代码所示)。

如何停止/修复此问题?我希望线条保持为一条不会使画布着色的单线。

Math.clamp = function(x, min, max) {
  return x < min ? min : (x > max ? max : x);
};

// canvas settings
var viewWidth = window.innerWidth,
  viewHeight = window.innerHeight,
  drawingCanvas = document.getElementById("drawing_canvas"),
  ctx,
  timeStep = (10 / 100),
  time = 0;

var lineTension = 0.067,
  lineDamping = 0.068,
  waveSpreadFactor = 0.1;

var previousMousePosition = {
    x: 0,
    y: 0
  },
  currentMousePosition = {
    x: 0,
    y: 0
  },
  actualMousePosition = {
    x: 0,
    y: 0
  };

var line,
  lineSegmentCount = 64,
  lineMaxForce = 32,
  lineStrokeGradient;

var audioCtx,
  nodeCount = 64,
  oscillatorNodes = [],
  gainNodes = [];

var segmentsPerNode = lineSegmentCount / nodeCount;

function initGui() {

}

function goBananas() {
  lineTension = 0.2;
  line.anchors[Math.floor(Math.random() * line.anchors.length)].
  vel = lineMaxForce;
}

function resetLine() {
  line.reset();

  for (var i = 0; i < nodeCount; i++) {
    oscillatorNodes[i].detune.value = 100;
    gainNodes[i].gain.value = 0;
  }

  lineTension = 0.0025;
  lineDamping = 0.05;
  waveSpreadFactor = 0.1;
}

function initDrawingCanvas() {
  drawingCanvas.width = viewWidth;
  drawingCanvas.height = viewHeight;

  window.addEventListener('resize', resizeHandler);
  window.addEventListener('mousemove', mouseMoveHandler);
  setInterval(updateMousePosition, (1000 / 30));

  ctx = drawingCanvas.getContext('2d');
  ctx.lineWidth = 5;

  line = new Line(0, viewHeight * 0.5, viewWidth, lineSegmentCount);
  // line.anchors[0].vel = viewHeight * 0.25;

  lineStrokeGradient = ctx.createLinearGradient(0, 0, 0, viewHeight);
  lineStrokeGradient.addColorStop(0, '#0ff');
}

function initWebAudio() {
  audioCtx = new(window.AudioContext || window.webkitAudioContext)();

  for (var i = 0; i < nodeCount; i++) {
    var oscillatorNode = audioCtx.createOscillator();
    var gainNode = audioCtx.createGain();

    oscillatorNode.connect(gainNode);
    gainNode.connect(audioCtx.destination);

    gainNode.gain.value = 0;

    oscillatorNode.type = 'saw';
    oscillatorNode.detune.value = 200;
    oscillatorNode.frequency.value = 1200 * (i / 60);
    oscillatorNode.start();

    oscillatorNodes[i] = oscillatorNode;
    gainNodes[i] = gainNode;
  }
}

function resizeHandler() {
  drawingCanvas.width = viewWidth = window.innerWidth;
  drawingCanvas.height = viewHeight = window.innerHeight;

  if (ctx) {
    ctx.lineWidth = 4;
    line.resize(viewWidth, viewHeight * 0.5);
  }
}

function mouseMoveHandler(event) {
  actualMousePosition.x = Math.floor(event.clientX);
  actualMousePosition.y = Math.floor(event.clientY);
}

function updateMousePosition() {
  previousMousePosition.x = currentMousePosition.x;
  previousMousePosition.y = currentMousePosition.y;
  currentMousePosition.x = actualMousePosition.x;
  currentMousePosition.y = actualMousePosition.y;
}

function update() {
  var px = Math.min(previousMousePosition.x, currentMousePosition.x),
    py = Math.min(previousMousePosition.y, currentMousePosition.y),
    pw = Math.max(1, Math.abs(previousMousePosition.x - currentMousePosition.x)),
    ph = Math.max(1, Math.abs(previousMousePosition.y - currentMousePosition.y)),
    force = Math.clamp(currentMousePosition.y -
      previousMousePosition.y, -lineMaxForce, lineMaxForce);

  var pixels = ctx.getImageData(px, py, pw, ph),
    data = pixels.data;

  for (var i = 0; i < data.length; i += 3) {
    var r = data[i + 0],
      g = data[i + 1],
      b = data[i + 2],
      x = (i % ph) + px;

    if (r + g + b > 0) {
      line.ripple(x, force);
    }
  }

  line.update();

  for (var j = 0; j < gainNodes.length; j++) {
    var anchor = line.anchors[j * segmentsPerNode],
      gain = Math.clamp(Math.abs(anchor.vel) / viewHeight * 0.5, 0, 3),
      detune = Math.clamp(anchor.pos / viewHeight * 100, 0, 300);

    gainNodes[j].gain.value = gain;
    oscillatorNodes[j].detune.value = detune;
  }
}

function draw() {

  ctx.strokeStyle = lineStrokeGradient;
  line.draw();
}

window.onload = function() {
  initDrawingCanvas();
  initWebAudio();
  initGui();

  requestAnimationFrame(loop);
};

function loop() {
  update();
  draw();
  time += timeStep;
  requestAnimationFrame(loop);
}



Line = function(x, y, length, segments) {
  this.x = x;
  this.y = y;
  this.length = length;
  this.segments = segments;

  this.segmentLength = this.length / this.segments;
  this.anchors = [];

  for (var i = 0; i <= this.segments; i++) {
    this.anchors[i] = {
      target: this.y,
      pos: this.y,
      vel: 0,
      update: function() {
        var dy = this.pos - this.target,
          acc = -lineTension * dy - lineDamping * this.vel;

        this.pos += this.vel;
        this.vel += acc;
      },
      reset: function() {
        this.pos = this.target;
        this.vel = 0;
      }
    };
  }
};

Line.prototype = {
  resize: function(length, targetY) {
    this.length = length;
    this.segmentLength = this.length / this.segments;

    for (var i = 0; i <= this.segments; i++) {
      this.anchors[i].target = targetY;
    }
  },
  reset: function() {
    for (var i = 0; i <= this.segments; i++) {
      this.anchors[i].reset();
    }
  },
  ripple: function(origin, amplitude) {
    var i = Math.floor((origin - this.x) / this.segmentLength);

    if (i >= 0 && i <= this.segments) {
      this.anchors[i].vel = amplitude;
    }
  },
  update: function() {
    var lDeltas = [],
      rDeltas = [],
      i;

    for (i = 0; i <= this.segments; i++) {
      this.anchors[i].update();
    }

    for (i = 0; i <= this.segments; i++) {
      if (i > 0) {
        lDeltas[i] = waveSpreadFactor * (this.anchors[i].pos - this.anchors[i - 1].pos);
        this.anchors[i - 1].vel += lDeltas[i];
      }
      if (i < this.segments) {
        rDeltas[i] = waveSpreadFactor * (this.anchors[i].pos - this.anchors[i + 1].pos);
        this.anchors[i + 1].vel += rDeltas[i];
      }
    }

    for (i = 0; i <= this.segments; i++) {
      if (i > 0) {
        this.anchors[i - 1].pos += lDeltas[i];
      }
      if (i < this.segments) {
        this.anchors[i + 1].pos += rDeltas[i];
      }
    }
  },
  draw: function() {
    ctx.beginPath();

    for (var i = 0; i <= this.segments; i++) {
      ctx.lineTo(
        this.x + this.segmentLength * i,
        this.anchors[i].pos
      );
    }
    ctx.stroke();
  }
};

1 个答案:

答案 0 :(得分:0)

从您发布的代码中,问题似乎是缺失

ctx.clearRect(0, 0, viewWidth, viewHeight)

在你的'#34;画&#34;开始时功能

See a working example here