2012-06-27 17 views
6
<img src="circle.png" onclick="alert('clicked')"/> 

मान लें कि circle.png बीच में किसी मंडली के साथ 400x400 पिक्सल पारदर्शी पृष्ठभूमि छवि में है।चित्र नक्शे अल्फ़ा चैनल द्वारा

क्या मैं अब मिल गया है कि पूरी छवि क्षेत्र (400x400px) क्लिक करने योग्य है। मुझे क्या चाहिए यह है कि केवल सर्कल (गैर पारदर्शी पिक्सेल) क्लिक करने योग्य हैं।

बेशक मुझे पता है कि इस उदाहरण में मैं <map> टैग और एक परिपत्र क्षेत्र का उपयोग कर सकता हूं, लेकिन मैं एक सामान्य समाधान की तलाश कर रहा हूं जो वास्तविक छवि पारदर्शिता को ध्यान में रखेगा और किसी भी प्रकार की छवियों के लिए काम करेगा (यानी गैर नियमित आकार)।

सबसे जटिल तरह से मैं देख सकता था, प्रत्येक पिक्सेल अल्फा पर छवि आधारित की समोच्च का पता लगाने के लिए एक रास्ता में कन्वर्ट (शायद आसान बनाने में) और एक नक्शे के रूप में लागू करने के लिए है।

क्या ऐसा करने के लिए एक और अधिक कुशल/सीधा तरीका है?

+0

आप की जरूरत है ऐसा करने के लिए क्योंकि छवियों को गतिशील रूप से उत्पन्न किया जाएगा? जबकि मुझे यकीन है कि यह जावास्क्रिप्ट में किया जा सकता है, यह शायद धीमा होने जा रहा है। फ़ोटोशॉप में "जादू की छड़ी" और क्या नहीं है, इसे "इसे सही" करने के लिए तुच्छ नहीं है। ऐसा लगता है कि यदि आप छवियों को गतिशील रूप से उत्पन्न कर रहे हैं, तो छविमैप बनाने के लिए स्रोत डेटा का उपयोग करें। यदि आप नहीं हैं, तो इसे ऑफ़लाइन क्यों न करें और छविमैप का उपयोग क्यों करें? –

+0

हाँ, जो गतिशील रूप से होने जा रहा है क्योंकि छवियों को भी गतिशील रूप से लोड किया जाएगा ... – lviggiani

उत्तर

17

canvas टैग का उपयोग करना, आप किसी दिए गए स्थान के तहत एक पिक्सेल के रंग मूल्य निर्धारित कर सकते हैं। आप निर्देशांक निर्धारित करने के लिए ईवेंट डेटा का उपयोग कर सकते हैं, फिर पारदर्शिता की जांच करें। यह सब बनी हुई है जो छवि को कैनवास में लोड कर रही है।

सबसे पहले, हम इस बात का ध्यान रखेंगे:

var ctx = document.getElementById('canvas').getContext('2d'); 
    var img = new Image(); 
    img.onload = function(){ 
    ctx.drawImage(img,0,0); 
    }; 
    img.src = [YOUR_URL_HERE]; 

यह पहली बिट पकड़ लेता है कैनवास तत्व है, तो एक Image वस्तु बनाता है। जब छवि लोड होती है, तो यह कैनवास पर खींची जाती है। बहुत सीधा! इसके अलावा ... यदि छवि कोड के समान डोमेन पर नहीं है, तो आप उसी डोमेन नीति सुरक्षा के विरुद्ध हैं। हमारी छवि का डेटा प्राप्त करने के लिए, हमें स्थानीय रूप से होस्ट होने वाली छवि की आवश्यकता होगी। आप अपनी छवि को बेसोड एन्कोड भी कर सकते हैं, जो इस उत्तर के दायरे से बाहर है। (ऐसा करने के लिए टूल के लिए this url देखें)।

अगला, कैनवास पर अपना क्लिक ईवेंट संलग्न करें। जब कि क्लिक में आता है, हम पारदर्शिता के लिए जाँच करें और केवल गैर-पारदर्शी क्लिक क्षेत्रों के लिए कार्य करेंगे:

if (isTransparentUnderMouse(this, e)) 
     return; 
    // do whatever you need to do 
    alert('will do something!'); 

जादू समारोह isTransparentUnderMouse है, जो दो तर्क की जरूरत में क्या होता है: में लक्ष्य कैनवास तत्व (this हैंडलर के दायरे पर क्लिक करें) और घटना डेटा (ई, इस उदाहरण में)। अब हम मांस पर आते हैं:

var isTransparentUnderMouse = function (target, evnt) { 
    var l = 0, t = 0; 
    if (target.offsetParent) { 
     var ele = target; 
     do { 
      l += ele.offsetLeft; 
      t += ele.offsetTop; 
     } while (ele = ele.offsetParent); 
    } 
    var x = evnt.page.x - l; 
    var y = evnt.page.y - t; 
    var imgdata = target.getContext('2d').getImageData(x, y, 1, 1).data; 
    if (
     imgdata[0] == 0 && 
     imgdata[1] == 0 && 
     imgdata[2] == 0 && 
     imgdata[3] == 0 
    ){ 
     return true; 
    } 
    return false; 
}; 

सबसे पहले, हम प्रश्न में तत्व की सटीक स्थिति प्राप्त करने के लिए कुछ नृत्य करते हैं। हम कैनवास तत्व को पास करने के लिए उस जानकारी का उपयोग करने जा रहे हैं। getImageData हमें अन्य चीज़ों के साथ, data ऑब्जेक्ट देगा जिसमें हमारे द्वारा निर्दिष्ट स्थान के आरजीबीए शामिल हैं।

यदि ये सभी मान 0 हैं, तो हम पारदर्शिता को देख रहे हैं। यदि नहीं, तो कुछ रंग मौजूद है। -एडिट- जैसा कि टिप्पणियों में उल्लेख किया गया है, उपरोक्त उदाहरण में हमें केवल एक ही मूल्य देखने की आवश्यकता है, imgdata[3]। मान आर (0) जी (1) बी (2) ए (3) हैं, और पारदर्शिता ए, अल्फा द्वारा निर्धारित की जाती है। आप किसी भी अस्पष्टता पर किसी भी रंग को खोजने के लिए इस दृष्टिकोण का उपयोग कर सकते हैं जिसे आप आरजीबीए डेटा जानते हैं।

यहाँ इसे आजमाएं: http://jsfiddle.net/pJ3MD/1/

(ध्यान दें:। मेरे उदाहरण में, मैं डोमेन सुरक्षा मैंने कहा आप कोड के उस भाग की उपेक्षा कर सकते जब तक कि आप भी चाहते हैं की वजह से एक बेस 64 इनकोडिंग छवि का इस्तेमाल किया माउस कर्सर में परिवर्तन मनोरंजन के लिए में फेंक दिया के साथ बेस 64 एन्कोडिंग)

एक ही उदाहरण के लिए, का उपयोग करने पर: http://jsfiddle.net/pJ3MD/2/

प्रलेखन

MDN पर
+0

+1। यह भी +1 क्योंकि यह एक अच्छा जवाब है! – Bojangles

+0

यह बहुत अच्छा विचार है! बहुत धन्यवाद! – lviggiani

+0

isransparentUnderMouse के लिए बस एक कॉस्मेटिक सुधार: वापसी (imgdata [0] + imgdata [1] + imgdata [2] + imgdata [3] == 0) – lviggiani

4

आप एचटीएमएल 5 कैनवास का उपयोग कर ऐसा कर सकते हैं। छवि को कैनवास में खींचें, कैनवास पर एक क्लिक हैंडलर संलग्न करें, और हैंडलर में, जांचें कि क्लिक किया गया पिक्सेल पारदर्शी है या नहीं।

+1

आह, हमने इस पर एक जैसे विचार किया, मुझे आपका जवाब नहीं मिला क्योंकि इसे सब कुछ करने में एक मिनट लग गया! चीयर्स! आपके द्वारा इस उत्तर में दिए गए प्रयास के लिए –

1

इस महान जवाब

मैं कोड के लिए कुछ लाइनें जोड़ा कैनवास

तो

क्या मैं अब ठीक की एक कैनवास पैदा कर रही है स्केलिंग के साथ संभाल करने के लिए आप क्रिस धन्यवाद पिक्सेल आकार उस छवि पर खींचा गया है। की तरह (एक छवि के लिए 220px * 120px):

<canvas width="220" height="120" id="mainMenu_item"></canvas> 

और सीएसएस का उपयोग कर कैनवास पैमाने:

#mainMenu_item{ width:110px; }

और समायोजित isTransparentUnderMouse समारोह की तरह दिखता है:

var isTransparentUnderMouse = function (target, evnt) { 

    var l = 0, t = 0; 
    if (target.offsetParent) { 
     var ele = target; 
     do { 
      l += ele.offsetLeft; 
      t += ele.offsetTop; 
     } while (ele = ele.offsetParent); 
    } 

    var x = evnt.pageX - l; 
    var y = evnt.pageY - t; 

    var initialWidth = $(evnt.target).attr('width'); 
    var clientWidth = evnt.target.clientWidth; 
    x = x * (initialWidth/clientWidth); 

    var initialHeight = $(evnt.target).attr('height');; 
    var clientHeight = evnt.target.clientHeight; 
    y = y * (initialHeight/clientHeight); 

    var imgdata = target.getContext('2d').getImageData(x, y, 1, 1).data; 

    if (
     imgdata[0] == 0 && 
     imgdata[1] == 0 && 
     imgdata[2] == 0 && 
     imgdata[3] == 0 
    ){ 
     return true; 
    } 
    return false; 
};