2015-02-10 3 views
2

У меня есть холст HTML5. Я использую библиотеку холста KineticJS(KonvaJS). На пустом холсте я рисую изображение, как показано на рисунке ниже. Теперь я хочу создать кругную форму, которая может использоваться для стирания частей изображения. Красный круг на изображении - это ластик.Удаление частей изображения на холсте HTML5?

enter image description here

Как я могу стереть часть изображения на HTML5 Canvas?

+0

Пожалуйста, не «цепь» провести дополнительное по вопросам к первоначальному вопросу. Это часто меняет основу ответа. Это, безусловно, касается этого вопроса, который вы задаете. Благодаря! ;-) – markE

ответ

3

Вы можете использовать Compositing для «удаления» пикселей.

В частности вы используете композицию destination-out.

KineticJS не поддерживает композитинга, но у вас еще есть несколько вариантов:

(Примечание. KineticJS стала KonvaJS, и я не проверенными, поддерживает ли KonvaJs композитинга Если теперь делает, просто использовать destination-out композитинга внутри KonvaJS)

Вариант № 1: Используйте родной элемент холста в качестве источника Kinetic.Image

  • Создание html5 холста в памяти с помощью var c=document.createElement,

  • Изменения размера холста к размеру изображения,

  • drawImage изображения на холст,

  • Создать Kinetic.Image и установите его свойство изображения к ссылка на собственный холст. Kinetic.Image отобразит все, что нарисовано на нативном холсте.

    var kImage=new Kinetic.Image({ 
    ... 
    image:c, 
    ... 
    
  • Установите холст композитинга, чтобы вызвать новые рисунки «стереть» существующие пиксели:

    c.globalCompositeOperation='destination-out'; 
    
  • Прислушайтесь событий перетаскивания на ваш круг-резинкой. Используйте эти события, чтобы нарисовать круг на холсте, который перемещается так же, как и кинетический круговой ластик.Поскольку композиция холста установлена ​​на «стирание», новые рисунки круга на холсте стирают изображение на холсте.

Ваш Kinetic.Image точно отражает его источник холста (вар с), так что ваш Kinetic.Image будет также отображать изображение стирается в ответ на Kinetic движений круга-ластик.

Вариант № 2: Используйте Kinetic.Shape

Вы можете сделать ту же операцию Варианта № 1, создав Kinetic.Shape на отдельный слой и получить ссылку на родной контекст холста с помощью:

var ctx = myShapeLayer.getContext()._context; 

Это более слабый вариант, потому что KineticJS будет перерисовывать форму - причина вашего стирания, чтобы отменить. Поэтому вы должны сделать дополнительный шаг для сохранения всех движений вашего круга и повторения этих движений (в drawFunc), чтобы повторить стирание.

+0

Есть ли способ изменить силу ластика? Кое-что вроде значения силы, которое определяет 0, означает, что стирание пикселя и 1 значащего пикселя будет стерто. Пока все значения между 0 и 1 определяют, насколько сильно стирает стиратель на стираемом пикселе. – confile

+0

Я догадываюсь, что вы спрашиваете о объединении альфы с композицией. Вы можете это сделать, но вы должны спросить об этом в новом вопросе, так как ваш исходный вопрос ничего не говорит об альфа-смешении. ;-) – markE

+0

Возникает вопрос: http://stackoverflow.com/questions/28441093/how-can-i-combine-alpha-with-compositing-in-images – confile

0

В простом JavaScript это довольно прямолинейно.

Сначала получите свой холст и контекст рисования готовый:

var context=document.getElementById("your_canvas_id").getContext("2d"); 
var image=document.getElementById("your_image_id"); 

Теперь вы хотите, чтобы сделать изображение в контексте:

context.drawImage(image,0,0,image.width,image.height,0,0,image.width,image.height); 

Теперь, когда вы хотите, чтобы стереть часть изображения, просто нарисуйте холст:

var x=y=radius=10;// Circle coordinates and radius. 

context.fillStyle="#ffffff";// Your eraser color (not transparent) 
context.beginPath(); 
context.arc(x,y,radius,0,Math.PI*2); 
context.fill(); 

Это только имитирует стирание. Если вы хотите, чтобы вы стирали, чтобы быть прозрачным впоследствии, вы можете посмотреть в context.clearRect, но я не уверен, как вы это сделаете с помощью круга.

+0

[link] (http://stackoverflow.com/questions/10396991/clearing-circular-regions-from-html5-canvas) В этой ссылке описывается, как на самом деле стереть круговую область вашего холста. – Frank

3

Спасибо за MARKE за его подробный ответ,

Я попытался получить контекст от Konva.Layer(), и она работала.

var freeHandDrawingImage = new Image(); 
    freeHandDrawingImage.onload = function() { 
     var context = freeHandDrawingLayer.getContext('2d'); 
     context.drawImage(this, 0,0); 
     context.globalCompositeOperation='destination-out'; 
     freeHandDrawingLayer.draw(); 
    }; 
    freeHandDrawingImage.src = "image.png"; 

и я использовал Konva.Shape, чтобы стереть с помощью "destination-out" и сделать бесплатный розыгрыш обычаем "source-over":

freeDrawingType = 'brush'; 
isFreeDrawingMode = false; 
isPaint = false; 
lastPointerPosition = {}; 

drawFreeDrawings = function(){ 

    var freeDraw = new Konva.Shape({ 
     name: "freeDraw", 
     stroke: 'black', 
     strokeWidth: 5, 
     closed : false, 
     sceneFunc: function(context){ 
      // free draw quad 
      debugger; 
      if(isPaint){ 
       if (freeDrawingType === 'brush') { 
        context.globalCompositeOperation = 'source-over'; 
       } 
       if (freeDrawingType === 'eraser') { 
        context.globalCompositeOperation = 'destination-out'; 
       } 
       context.beginPath(); 
       context.moveTo(lastPointerPosition.x, lastPointerPosition.y); 
       var newPosition = stage.getPointerPosition(); 

       context.lineTo(newPosition.x, newPosition.y); 
       context.stroke(); 
       debugger; 
       lastPointerPosition = newPosition; 
       context.strokeShape(this); 

      } 
     } 
    }); 
    freeHandDrawingLayer.add(freeDraw); 
    // now we need to bind some events 
    // we need to start drawing on mousedown 
    // and stop drawing on mouseup 
    selectionBoxBackground.on('mousedown', function() { 
     if(isFreeDrawingMode){ 
      isPaint = true; 
      lastPointerPosition = stage.getPointerPosition(); 
      stage.draw(); 
     } 
    }); 

    selectionBoxBackground.on('mouseup', function() { 
     if(isFreeDrawingMode){ 
      isPaint = false; 
     } 
    }); 

    // and core function - drawing 
    selectionBoxBackground.on('mousemove', function() { 
      if (!isPaint) { 
       return; 
      }  
      freeHandDrawingLayer.draw(); 
    }); 
}