2010-09-07 23 views
39

Tôi tự hỏi nếu có gì đó giống như 9-patch trong Android, nhưng để phát triển web?Hình ảnh chín vá để phát triển web

Tiết lộ: Tôi không biết gì về phát triển web cả, nhưng tôi tò mò muốn biết liệu nó có tồn tại hay không. Và một tìm kiếm web đơn giản với thuật ngữ 9-patch không mang lại bất kỳ kết quả liên quan nào, vì vậy tôi đã tìm ra nó có một thuật ngữ khác hoặc nó không tồn tại hoặc không được sử dụng rộng rãi đủ.

Có ai biết không?

+6

Cảm ơn bạn đã đặt câu hỏi này. Đó là chính xác những gì tôi đã tìm kiếm. –

+0

Nếu bạn muốn sử dụng jQuery, [câu trả lời này] (http://stackoverflow.com/a/6806707/386738) có thể hữu ích – Daniel

Trả lời

5

Nếu bạn vẫn quan tâm đến tôi tạo ra một tập tin javascript sử dụng vải để tạo ra hỗ trợ hình ảnh chín vá thực cho web. Các dự án mã nguồn mở có thể được tìm thấy ở đây:

https://github.com/chrislondon/9-Patch-Image-for-Websites

0

Vâng, tôi đã lấy những rắc rối để sửa lỗi sa mạc tôi tìm thấy trong các liên kết ở trên.

Biết NinePath android là một công cụ hữu ích bổ sung thêm bức tranh động và nhận dạng padding (bị thiếu trong lần chuyển tiền trước đó). Tôi có thể thêm một vài kịch bản cho chức năng hoàn chỉnh.

Thay thế mã sau trong đường dẫn thư viện9.js!

function NinePatchGetStyle(element, style) 
{ 
    if (window.getComputedStyle) 
    { 
     var computedStyle = window.getComputedStyle(element, ""); 
     if (computedStyle === null) 
      return ""; 
     return computedStyle.getPropertyValue(style); 
    } 
    else if (element.currentStyle) 
    { 
     return element.currentStyle[style]; 
    } 
    else 
    { 
     return ""; 
    } 
} 

// Cross browser function to find valid property 
function NinePatchGetSupportedProp(propArray) 
{ 
    var root = document.documentElement; //reference root element of document 
    for (var i = 0; i < propArray.length; i++) 
    { 
     // loop through possible properties 
     if (typeof root.style[propArray[i]] === "string") 
     { 
      //if the property value is a string (versus undefined) 
      return propArray[i]; // return that string 
     } 
    } 
    return false; 
} 


/** 
* 9patch constructer. Sets up cached data and runs initial draw. 
* @param {Dom Element} div El Elemento dom en donde se pinta el ninepath 
* @param {function} callback La funcion que se llamara cuando se termina 
* la carga de la imagen y el pintado del elemento div. 
* @returns {NinePatch} Un objeto nine path 
*/ 
function NinePatch(div,callback) 
{ 
    this.div = div; 
    this.callback =callback; 
    this.padding = {top:0,left:0,right:0,bottom:0}; 
    // Load 9patch from background-image 
    this.bgImage = new Image(); 
    this.bgImage.src = NinePatchGetStyle(this.div, 'background-image').replace(/"/g, "").replace(/url\(|\)$/ig, ""); 
    var este = this; 

    this.bgImage.onload = function() 
    { 
     este.originalBgColor = NinePatchGetStyle(este.div, 'background-color'); 
     este.div.style.background = 'none'; 

     // Create a temporary canvas to get the 9Patch index data. 
     var tempCtx, tempCanvas; 
     tempCanvas = document.createElement('canvas'); 
     tempCanvas.width = este.bgImage.width; 
     tempCanvas.height = este.bgImage.height; 
     tempCtx = tempCanvas.getContext('2d'); 
     tempCtx.drawImage(este.bgImage, 0, 0); 

     // Obteniendo el padding lateral derecho 
     var dataPad = tempCtx.getImageData(este.bgImage.width-1,0,1,este.bgImage.height).data; 
     var padRight = este.getPadBorder(dataPad,este.bgImage.width,este.bgImage.height); 
     este.padding.top = padRight.top; 
     este.padding.bottom = padRight.bottom; 
     dataPad = tempCtx.getImageData(0,este.bgImage.height-1,este.bgImage.width,1).data; 
     var padBottom = este.getPadBorder(dataPad,este.bgImage.width,este.bgImage.height); 

     este.padding.left = padBottom.top; 
     este.padding.right = padBottom.bottom; 

     // Loop over each horizontal pixel and get piece 
     var data = tempCtx.getImageData(0, 0, este.bgImage.width, 1).data; 

     // Use the upper-left corner to get staticColor, use the upper-right corner 
     // to get the repeatColor. 
     var tempLength = data.length - 4; 
     var staticColor = data[0] + ',' + data[1] + ',' + data[2] + ',' + data[3]; 
     var repeatColor = data[tempLength] + ',' + data[tempLength + 1] + ',' + 
       data[tempLength + 2] + ',' + data[tempLength + 3]; 

     este.horizontalPieces = este.getPieces(data, staticColor, repeatColor); 

     // Loop over each horizontal pixel and get piece 
     data = tempCtx.getImageData(0, 0, 1, este.bgImage.height).data; 
     este.verticalPieces = este.getPieces(data, staticColor, repeatColor); 

     // use this.horizontalPieces and this.verticalPieces to generate image 
     este.draw(); 
     este.div.onresize = function() 
     { 
      este.draw(); 
     }; 
     if(callback !== undefined) 
     { 
      if (typeof(callback) === "function") 
       callback(); 
     } 
    }; 
} 

// Stores the HTMLDivElement that's using the 9patch image 
NinePatch.prototype.div = null; 
// Padding 
NinePatch.prototype.padding = null; 
// Get padding 
NinePatch.prototype.callback = null; 
// Stores the original background css color to use later 
NinePatch.prototype.originalBG = null; 
// Stores the pieces used to generate the horizontal layout 
NinePatch.prototype.horizontalPieces = null; 
// Stores the pieces used to generate the vertical layout 
NinePatch.prototype.verticalPieces = null; 
// Stores the 9patch image 
NinePatch.prototype.bgImage = null; 

// Gets the horizontal|vertical pieces based on image data 
NinePatch.prototype.getPieces = function(data, staticColor, repeatColor) 
{ 
    var tempDS, tempPosition, tempWidth, tempColor, tempType; 
    var tempArray = new Array(); 

    tempColor = data[4] + ',' + data[5] + ',' + data[6] + ',' + data[7]; 
    tempDS = (tempColor === staticColor ? 's' : (tempColor === repeatColor ? 'r' : 'd')); 
    tempPosition = 1; 

    for (var i = 4, n = data.length - 4; i < n; i += 4) 
    { 
     tempColor = data[i] + ',' + data[i + 1] + ',' + data[i + 2] + ',' + data[i + 3]; 
     tempType = (tempColor === staticColor ? 's' : (tempColor === repeatColor ? 'r' : 'd')); 
     if (tempDS !== tempType) 
     { 
      // box changed colors 
      tempWidth = (i/4) - tempPosition; 
      tempArray.push(new Array(tempDS, tempPosition, tempWidth)); 

      tempDS = tempType; 
      tempPosition = i/4; 
      tempWidth = 1; 
     } 
    } 

    // push end 
    tempWidth = (i/4) - tempPosition; 
    tempArray.push(new Array(tempDS, tempPosition, tempWidth)); 
    return tempArray; 
}; 

NinePatch.prototype.getPadBorder = function(dataPad,width,height) 
{ 
    var staticRight = dataPad[0] + ',' + dataPad[1] + ',' + dataPad[2] + ',' + dataPad[3]; 
    var pad={top:0,bottom:0}; 

    // Padding para la parte superior 
    for (var i=0;i<dataPad.length;i+=4) 
    { 
     var tempColor = dataPad[i] + ',' + dataPad[i + 1] + ',' + dataPad[i + 2] + ',' + dataPad[i + 3]; 
     if(tempColor !==staticRight) 
      break; 
     pad.top++; 
    } 
    // padding inferior 
    for (var i=dataPad.length-4;i>=0;i-=4) 
    { 
     var tempColor = dataPad[i] + ',' + dataPad[i + 1] + ',' + dataPad[i + 2] + ',' + dataPad[i + 3]; 
     if(tempColor !==staticRight) 
      break; 
     pad.bottom++; 
    } 
    return pad; 
}; 

// Function to draw the background for the given element size. 
NinePatch.prototype.draw = function() 
{ 
    var dCtx, dCanvas, dWidth, dHeight; 

    if(this.horizontalPieces === null) 
     return; 
    dWidth = this.div.offsetWidth; 
    dHeight = this.div.offsetHeight; 

    dCanvas = document.createElement('canvas'); 
    dCtx = dCanvas.getContext('2d'); 

    dCanvas.width = dWidth; 
    dCanvas.height = dHeight; 

    var fillWidth, fillHeight; 

    // Determine the width for the static and dynamic pieces 
    var tempStaticWidth = 0; 
    var tempDynamicCount = 0; 

    for (var i = 0, n = this.horizontalPieces.length; i < n; i++) 
    { 
     if (this.horizontalPieces[i][0] === 's') 
      tempStaticWidth += this.horizontalPieces[i][2]; 
     else 
      tempDynamicCount++; 
    } 

    fillWidth = (dWidth - tempStaticWidth)/tempDynamicCount; 

    // Determine the height for the static and dynamic pieces 
    var tempStaticHeight = 0; 
    tempDynamicCount = 0; 
    for (var i = 0, n = this.verticalPieces.length; i < n; i++) 
    { 
     if (this.verticalPieces[i][0] === 's') 
      tempStaticHeight += this.verticalPieces[i][2]; 
     else 
      tempDynamicCount++; 
    } 

    fillHeight = (dHeight - tempStaticHeight)/tempDynamicCount; 

    // Loop through each of the vertical/horizontal pieces and draw on 
    // the canvas 
    for (var i = 0, m = this.verticalPieces.length; i < m; i++) 
    { 
     for (var j = 0, n = this.horizontalPieces.length; j < n; j++) 
     { 
      var tempFillWidth, tempFillHeight; 

      tempFillWidth = (this.horizontalPieces[j][0] === 'd') ? 
        fillWidth : this.horizontalPieces[j][2]; 
      tempFillHeight = (this.verticalPieces[i][0] === 'd') ? 
        fillHeight : this.verticalPieces[i][2]; 

      // Stretching : 
      if (this.verticalPieces[i][0] !== 'r') { 
       // Stretching is the same function for the static squares 
       // the only difference is the widths/heights are the same. 
       dCtx.drawImage(
         this.bgImage, 
         this.horizontalPieces[j][1], this.verticalPieces[i][1], 
         this.horizontalPieces[j][2], this.verticalPieces[i][2], 
         0, 0, 
         tempFillWidth, tempFillHeight); 
      } else { 
       var tempCanvas = document.createElement('canvas'); 
       tempCanvas.width = this.horizontalPieces[j][2]; 
       tempCanvas.height = this.verticalPieces[i][2]; 

       var tempCtx = tempCanvas.getContext('2d'); 
       tempCtx.drawImage(this.bgImage, 
         this.horizontalPieces[j][1], this.verticalPieces[i][1], 
         this.horizontalPieces[j][2], this.verticalPieces[i][2], 
         0, 0, 
         this.horizontalPieces[j][2], this.verticalPieces[i][2]); 

       var tempPattern = dCtx.createPattern(tempCanvas, 'repeat'); 
       dCtx.fillStyle = tempPattern; 
       dCtx.fillRect(
         0, 0, 
         tempFillWidth, tempFillHeight); 
      } 

      // Shift to next x position 
      dCtx.translate(tempFillWidth, 0); 
     } 

     // shift back to 0 x and down to the next line 
     dCtx.translate(-dWidth, (this.verticalPieces[i][0] === 's' ? this.verticalPieces[i][2] : fillHeight)); 
    } 

    // store the canvas as the div's background 
    var url = dCanvas.toDataURL("image/png"); 
    var tempIMG = new Image(); 

    var _this = this; 
    tempIMG.onload = function(event) 
    { 
     _this.div.style.background = _this.originalBgColor + " url(" + url + ") no-repeat"; 
    }; 
    tempIMG.src = url; 
}; 


The usage is the following: 


    var elemDom = document.getElementById("idDiv"); 
    var background = "border.9.png"; 
    if (background.match(/\.9\.(png|gif)/i)) // Es nine path? 
    { 
     elemDom.style.backgroundRepeat = "no-repeat"; 
     elemDom.style.backgroundPosition = "-1000px -1000px"; 
     elemDom.style.backgroundImage = "url('"+background+"')"; 
     var ninePatch = new NinePatch(elemDom,function() 
     { 
      elemDom.style.paddingLeft = ninePatch.padding.left; 
      elemDom.style.paddingTop = ninePatch.padding.top; 
      elemDom.style.paddingRight = ninePatch.padding.right; 
      elemDom.style.paddingBottom = ninePatch.padding.bottom; 
     }); 
    } 
Các vấn đề liên quan