2012-04-09 31 views
8

Có cách nào để thay đổi màu sắc của hình ảnh giống như trong Flash/ActionScript chỉ bằng HTML5/CSS/JavaScript không?Canvas - Thay đổi màu của hình ảnh bằng HTML5/CSS/JS?

Dưới đây là ví dụ trong Flash: http://www.kirupa.com/developer/actionscript/color.htmEDIT: Đây là quá trình tôi muốn sao chép.

Tôi đang cố gắng thực hiện một cái gì đó như thế này (khía cạnh thay đổi màu sắc, bảo quản ánh sáng và bóng tối): http://www.acura.com/ExteriorColor.aspx?model=TL KHÔNG nạp & thay thế hình ảnh mới mỗi lần; Tôi muốn có thể thay đổi tông màu đơn giản (ví dụ: thực hiện phương thức HTML5/CSS/JS thuần túy). EDIT: Đây là kết quả tôi muốn đạt được, không phải là quá trình.

Về cơ bản, tôi muốn thay đổi bảng màu/tông màu của hình ảnh, đồng thời bảo toàn các khía cạnh khác của hình ảnh (chẳng hạn như độ dốc, ánh sáng, v.v ...). Tôi đã đến gần, nhưng không đủ gần; Tôi đã nhận được điểm mà tôi sử dụng một mặt nạ hình ảnh và tổng hợp trên hình ảnh gốc (loại giống như một lớp phủ hình ảnh trong suốt). Dưới đây là một số mã mẫu (xin lưu ý đây chỉ là một đoạn mã, vì vậy nó có thể hoặc không hoạt động; Tôi chỉ hiển thị mã mẫu để bạn có ý tưởng về những gì tôi đang cố gắng làm):

<div id='mask'> 
    <canvas id='canvas' width='100' height='100'></canvas> 
</div> 
<button data-rgba='255,0,0,0.5'>red</button> 
<button data-rgba='0,255,0,0.5'>green</button> 

<script> 
foo = {}; 
foo.ctx = jQuery('#canvas')[0]; 
foo.ctx_context = foo.ctx.getContext('2d'); 
foo.mask = jQuery('#mask')[0]; 
foo.img = new Image(); 
foo.img_path = '/path/to/image_mask.png'; // 100px x 100px image 

foo.changeColor = function(rgba){ 
    foo.ctx_context.clearRect(0, 0, 100, 100); 
    foo.ctx_context.fillStyle = 'rgba(' + rgba + ')'; 
    foo.ctx_context.fillRect(0, 0, 100, 100); 
    foo.ctx_context.globalCompositeOperation = 'destination-atop'; 
    foo.ctx_context.drawImage(foo.img, 0, 0); 
    foo.ctx_context.css({'background-image': "url(" + foo.ctx.toDataURL("image/png") + ")"}); 
}; 

jQuery("button").click(function(){ 
    foo.changeColor(jQuery(this).attr('data-rgba')); 
}); 
</script> 

Vấn đề chính khi sử dụng phương pháp này là hình ảnh trông thực sự phẳng. Có một cái gì đó khác mất tích, hoặc mặt nạ tôi đang sử dụng (mà là một hình ảnh trắng hình dạng bất thường rắn), là cách tiếp cận sai lầm.

+0

Vui lòng đăng câu đố hoàn chỉnh sau khi bạn có câu trả lời. Cảm ơn! – iambriansreed

Trả lời

-1

Thường làm một việc như thay đổi pixel ảnh bằng pixel là thứ bạn muốn làm ở phía máy chủ, vì nó rất nặng đối với trình duyệt. Trong trường hợp của trang web Acura không có gì khó khăn xảy ra - họ chỉ có một loạt các JPG khác nhau. Bạn cũng có thể thử xem xét Processing.js.

+0

Tôi không vẽ bất kỳ pixel nào theo pixel; Tôi đang tổng hợp một hình ảnh mặt nạ trên một hình ảnh hiện có, đó là MUCH nhanh hơn truy vấn back-end mỗi lần để làm một sự thay đổi màu sắc. Điều Acura đang làm là kết quả tôi muốn đạt được, nhưng KHÔNG phải là quá trình. Flash thay đổi màu sắc/tông màu rất tốt (ngay lập tức), nhưng thực tế đáng buồn là bạn không thể sử dụng Flash trên iPad, đó là lý do tại sao tôi tìm kiếm giải pháp HTML5. –

2

Chắc chắn, bạn có thể lấy dữ liệu pixel và thực hiện các điều chỉnh HSV trên đó. Phương thức bạn muốn là getImageData (trả về một UInt8Array, không phải là một mảng js bình thường).

Có một ghi chú thú vị here sẽ giúp bạn bắt đầu. Bạn có thể lớp các phần tử canvas trong suốt trên đầu trang của mỗi khác, mà sẽ giúp tránh các vấn đề với điều chỉnh các thành phần cơ sở (trong ví dụ xe hơi của bạn, lốp xe, cửa sổ, vv).

11

Chức năng này đòi hỏi hình ảnh được nạp và nó phải là từ cùng một tên miền (do chính sách miền chéo)

function tintImage(imgElement,tintColor) { 
    // create hidden canvas (using image dimensions) 
    var canvas = document.createElement("canvas"); 
    canvas.width = imgElement.offsetWidth; 
    canvas.height = imgElement.offsetHeight; 

    var ctx = canvas.getContext("2d"); 
    ctx.drawImage(imgElement,0,0); 

    var map = ctx.getImageData(0,0,320,240); 
    var imdata = map.data; 

    // convert image to grayscale 
    var r,g,b,avg; 
    for(var p = 0, len = imdata.length; p < len; p+=4) { 
     r = imdata[p] 
     g = imdata[p+1]; 
     b = imdata[p+2]; 
     // alpha channel (p+3) is ignored   

     avg = Math.floor((r+g+b)/3); 

     imdata[p] = imdata[p+1] = imdata[p+2] = avg; 
    } 

    ctx.putImageData(map,0,0); 

    // overlay filled rectangle using lighter composition 
    ctx.globalCompositeOperation = "lighter"; 
    ctx.globalAlpha = 0.5; 
    ctx.fillStyle=tintColor; 
    ctx.fillRect(0,0,canvas.width,canvas.height); 

    // replace image source with canvas data 
    imgElement.src = canvas.toDataURL(); 
} 

Giả sử đánh dấu của bạn trông như thế này:

<img id='myimage' src='image.jpg'/> 

Bạn có thể sử dụng nó bằng cách gọi nó với các thông số sau:

tintImage(
    document.getElementById('myImage'), 
    "#550000" // for a redish tint 
); 

Ví dụ làm việc tại đây: http://jsfiddle.net/pHwmL/1/

+1

Lưu ý rằng khi bạn nói tên miền chéo, mọi người sử dụng chrome để phát triển cục bộ cũng sẽ không thể thấy hoạt động này (tôi luôn chạy trên máy chủ web cục bộ để xác minh nó sẽ hoạt động.) Tôi thích phương pháp của bạn , nhưng thấy rằng nó ghi đè bất kỳ kênh alpha nào ... vì vậy tôi đã thêm một mảng chữ cái rồi viết lại chúng sau đó. Hoạt động tốt. Mã tại: https://github.com/jaycrossler/django-gamification/blob/master/gamification/static/themes/camping/badges.js#L711-L733 – JayCrossler

Các vấn đề liên quan