JavaScript寫一個簡單的Ps濾鏡效果

效果預覽

clipboard.png

思路

其實非常非常趕單~
CSS3多了一個filter的屬性,非常強大(兼容性一般)!
我們只要根據輸入的值/滑塊滑動的值來動態更改css中filter屬性的值即可

filter

  • none 默認值,沒有效果。
  • blur(px) 給圖像設置高斯模糊。"radius"一值設定高斯函數的標準差,或者是屏幕上以多少像素融在一起, 所以值越大越模糊;不接受百分比值。
  • brightness(%) 給圖片應用一種線性乘法,使其看起來更亮或更暗。如果值是0%,圖像會全黑。值是100%,則圖像無變化。其他的值對應線性乘數效果。值超過100%也是可以的,圖像會比原來更亮。如果沒有設定值,默認是1。
  • contrast(%) 調整圖像的對比度。值是0%的話,圖像會全黑。值是100%,圖像不變。值可以超過100%,意味着會運用更低的對比。若沒有設置值,默認是1。
  • drop-shadow(h-shadow v-shadow blur spread color) 給圖像設置一個陰影效果。陰影是合成在圖像下面,可以有模糊度的,可以以特定顏色畫出的遮罩圖的偏移版本。 函數接受<shadow>(在CSS3背景中定義)類型的值,除了"inset"關鍵字是不允許的。該函數與已有的box-shadow box-shadow屬性很相似;不同之處在於,通過濾鏡,一些瀏覽器爲了更好的性能會提供硬件加速
  • grayscale(%) 將圖像轉換爲灰度圖像。值定義轉換的比例。值爲100%則完全轉爲灰度圖像,值爲0%圖像無變化。值在0%到100%之間,則是效果的線性乘子。若未設置,值默認是0;
  • hue-rotate(deg) 圖像應用色相旋轉。"angle"一值設定圖像會被調整的色環角度值。值爲0deg,則圖像無變化。若值未設置,默認值是0deg。該值雖然沒有最大值,超過360deg的值相當於又繞一圈。
  • invert(%) 反轉輸入圖像。值定義轉換的比例。100%的價值是完全反轉。值爲0%則圖像無變化。值在0%和100%之間,則是效果的線性乘子。 若值未設置,值默認是0。
  • opacity(%) 轉化圖像的透明程度。值定義轉換的比例。值爲0%則是完全透明,值爲100%則圖像無變化。值在0%和100%之間,則是效果的線性乘子,也相當於圖像樣本乘以數量。 若值未設置,值默認是1。該函數與已有的opacity屬性很相似,不同之處在於通過filter,一些瀏覽器爲了提升性能會提供硬件加速。
  • saturate(%) 轉換圖像飽和度。值定義轉換的比例。值爲0%則是完全不飽和,值爲100%則圖像無變化。其他值,則是效果的線性乘子。超過100%的值是允許的,則有更高的飽和度。 若值未設置,值默認是1。
  • sepia(%) 將圖像轉換爲深褐色。值定義轉換的比例。值爲100%則完全是深褐色的,值爲0%圖像無變化。值在0%到100%之間,則是效果的線性乘子。若未設置,值默認是0;
  • url() URL函數接受一個XML文件,該文件設置了 一個SVG濾鏡,且可以包含一個錨點來指定一個具體的濾鏡元素。

使用直接就這樣

img {
    -webkit-filter: contrast(200%); /* Chrome, Safari, Opera */
    filter: contrast(200%) opacity(0.5) //要多少屬性加多少;
}

開始操作

  • 寫一個過濾屬性滑塊和輸入框,互相綁定值,如果用vue就簡單了hhh
//html
     <li>
      <label for="contrast">對比度(0-200):</label>
      <input id="contrast" max="200" min="0" step="1" type="range">
      <input id="contrast-val" class="val-box" type="number">
    </li>
//js
//註冊過濾器
function filter(type) {
  //獲取濾鏡類型關聯的dom節點
  //綁定change事件,還有回車按鍵事件
  
  let ele = document.getElementById(type);
  let ele_val = document.getElementById(type + '-val');

  //輸入框輸入值按下回車,把值更新到滑塊上
  ele_val.addEventListener('keyup',function(e){
    if(e.keyCode == 13){
    ele.value = ele_val.value;
    //同時更新濾鏡效果
    setCss(type, ele_val.value);

    }
  })
   
 //滑塊滑動的時候,把值更新在右邊的輸入框中
  ele.addEventListener('change', function() {
    ele_val.value = ele.value;
    //同時更新濾鏡效果
    setCss(type, ele_val.value);
  });
}
  • 寫一個文件選擇,預覽圖片
//html
<input id="file" type="file" accept="image/*">
<!-- 圖片預覽框 -->
<div>
    <img id="img" src="" alt="">
</div>
//選擇文件
function fileSelect() {
  let img = document.getElementById('img');
  document.getElementById('file').onchange = function() {
    var reader = new FileReader();
    reader.onload = function(e) {
      img.src = e.target.result;
    }
    reader.readAsDataURL(this.files[0]);
  }
}
  • 寫一個根據輸入值更新CSS的方法
//更新css屬性
function setCss(type, val) {
  let img = document.getElementById('img');
  //已經存在某個濾鏡,更改濾鏡數值
  if (img.style.filter.indexOf(type) > -1) {
    //利用正則則出濾鏡名稱更改其值
    let reg = new RegExp("(?<=" + type + ")" + "\\(.*\\)", "g")
    img.style.filter = img.style.filter.replace(reg, function(match) { return `(${val/100})` });
  } else {
    //直接添加新濾鏡
    img.style.filter += `${type}(${val/100})`
  }
}

注意

  • 由於這個demo只是隨便寫寫,只是前幾天用到這個filter屬性感覺有點厲害,就拿來玩玩,文中的代碼寫得很醜,也沒什麼規範,只適用於‘寫來玩玩’的範疇,一些輸入驗證,節流,參數的規範都沒有做,見諒。
  • 本來還打算做一個導出使用濾鏡後的照片的,用的html2canvas來截圖導出,然後發現,它不支持!!!不支持這個css屬性!!截出來的圖是原圖!這可是真的難受啊馬飛,現在還沒有解決方案,如果有大佬知道如何保存使用濾鏡後的圖片到本地的,請在評論區留下您的想法,非常感謝!

辣雞源碼

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>photoshop-web</title>
</head>

<body>
  <ul>
    <li>
      <label for="brightness">亮度(0-200):</label>
      <input id="brightness" max="200" min="0" step="1" type="range">
      <input id="brightness-val" class="val-box" type="number">
    </li>
    <li>
      <label for="contrast">對比度(0-200):</label>
      <input id="contrast" max="200" min="0" step="1" type="range">
      <input id="contrast-val" class="val-box" type="number">
    </li>
    <li>
      <label for="grayscale">灰度(0-100):</label>
      <input id="grayscale" max="100" min="0" step="1" type="range">
      <input id="grayscale-val" class="val-box" type="number">
    </li>
    <li>
      <label for="saturate">飽和度(0-200):</label>
      <input id="saturate" max="200" min="0" step="1" type="range">
      <input id="saturate-val" class="val-box" type="number">
    </li>
    <li>
      <label for="opacity">透明度(0-100):</label>
      <input id="opacity" max="100" min="0" step="1" type="range">
      <input id="opacity-val" class="val-box" type="number">
    </li>
    <li>
      <label for="invert">反相(0-100):</label>
      <input id="invert" max="100" min="0" step="1" type="range">
      <input id="invert-val" class="val-box" type="number">
    </li>
  </ul>
  <button id="reset">重置效果</button>
  <input id="file" type="file" accept="image/*">
  <div>
    <img id="img" src="" alt="">
  </div>
</body>
<script>
//選擇文件
function fileSelect() {
  let img = document.getElementById('img');
  document.getElementById('file').onchange = function() {
    var reader = new FileReader();
    reader.onload = function(e) {
      img.src = e.target.result;
    }
    reader.readAsDataURL(this.files[0]);
  }
}
//重置效果
function reset() {
  let reset_btn = document.getElementById('reset');
  let val_boxes = document.getElementsByClassName('val-box');
  let val_arr = Array.prototype.slice.call(val_boxes);
  let img = document.getElementById('img');

  reset_btn.addEventListener('click', function() {
    //所有的數據輸入重置爲空
    val_arr.forEach(function(item) {
      item.value = "";
    });
    //去掉圖片的css屬性
    img.style.filter = "";
  })
}
//註冊過濾器
function filter(type) {
  //獲取濾鏡類型關聯的dom節點
  //綁定change事件
  //更改右側輸入框的顯示的值,以及更新濾鏡效果
  let ele = document.getElementById(type);
  let ele_val = document.getElementById(type + '-val');
  ele_val.addEventListener('keyup',function(e){
    if(e.keyCode == 13){
    ele.value = ele_val.value;
    setCss(type, ele_val.value);

    }
  })
  ele.addEventListener('change', function() {
    ele_val.value = ele.value;
    setCss(type, ele_val.value);
  });
}
//更新css屬性
function setCss(type, val) {
  let img = document.getElementById('img');
  //已經存在某個濾鏡,更改濾鏡數值
  if (img.style.filter.indexOf(type) > -1) {
    let reg = new RegExp("(?<=" + type + ")" + "\\(.*\\)", "g")
    img.style.filter = img.style.filter.replace(reg, function(match) { return `(${val/100})` });
  } else {
    //直接添加新濾鏡
    img.style.filter += `${type}(${val/100})`
  }
}
window.onload = function() {
  //亮度
  filter('brightness');
  //對比度
  filter('contrast');
  //灰度
  filter('grayscale');
  //飽和度
  filter('saturate');
  //透明度
  filter('opacity');
  //反相  
  filter('invert');
  //註冊重置
  reset();
  //註冊文件選擇
  fileSelect();
}
</script>

</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章