Photopea 之——一键转为 PNG/WebP

单张图片格式快捷转换

  1. // ==UserScript==
  2. // @name Photopea 之——一键转为 PNG/WebP
  3. // @description 单张图片格式快捷转换
  4. // @mechanism 不过是个鼠标和输入的宏
  5. // @version 1.0.2~20221211
  6. // @match https://www.photopea.com/
  7. // @license Unlicense
  8. // @namespace https://gf.qytechs.cn/users/871942
  9. // ==/UserScript==
  10.  
  11. // 自定义预设之例子:`localStorage.setItem('convertOptions', JSON.stringify({width:1280}))`
  12.  
  13. const fnName = '一键转 PNG/WebP'
  14. const [$, $$] = ['', 'All'].map(_ => document[`querySelector${_}`].bind(document))
  15.  
  16. addEventListener('load', () => {
  17. console.log(`「${fnName}」已加载!`)
  18. topbar(1).addEventListener('click', () => {
  19. const cp = $(`.contextpanel`), el = cp.querySelector('div:last-child').cloneNode(true)
  20. cp.insertAdjacentElement('beforeend', el).addEventListener('click', main)
  21. el.querySelector('.label').innerHTML = fnName
  22. }, { once: true })
  23. })
  24.  
  25.  
  26. function main() {
  27. if (/*当前无打开的项目*/!$('.panelhead > .active')) {
  28. clickMenu.msg = '打开文件'
  29. clickMenu(1,2)
  30. /*一开就转*/onAppend($('.panelhead'), main, {once:true})
  31. return
  32. }
  33.  
  34. const { width, fmt = 'PNG' } = JSON.parse(localStorage.getItem('convertOptions')) || {}
  35.  
  36. if (!isNaN(width)) {
  37. clickMenu.msg = `调整图片大小为 ${width} px`
  38. clickMenu(3,9)
  39. setParam([document.activeElement, width])
  40. click('.spread')
  41. }
  42.  
  43. clickMenu.msg = '调整视图大小'
  44. clickMenu(7,3)
  45.  
  46. clickMenu.msgEnd =
  47. clickMenu.msg = `导出 ${fmt}`
  48. switch (fmt.toLowerCase()) {
  49. case 'png': clickMenu(1,9,1); break
  50. case 'webp': clickMenu(1,9,-1,1); setParam([$('.trangeinput > input'), '100%']); break
  51. default: unsafeWindow.alert(`不支持一键导出 ${fmt} 格式`, 7000); return
  52. }
  53. click('.spread',0)
  54.  
  55. // 移除假阳性的反反广告弹框
  56. setTimeout(() => onAppend($('.app'), () => dE($('.confirm .cross'), 'pointerup'), {once:true, timeout:10000}))
  57. }
  58.  
  59.  
  60. function clickMenu(..._) {
  61. // 最核心的函数,移植定制你自己的其他操作流程之利器。系检试而成且即使某天原站界面大改大变也只需修改此处的CSS选择器
  62. let __, ___
  63. _[0] && (___ = topbar(_[0])) && ___.dispatchEvent(new Event('pointerdown'))
  64. Array.from(Array(_.length - 1).keys(), _ => ++_).every(n =>
  65. _[n] && (__ = $$(`.contextpanel`)[n-1]) && (__ = __.querySelector(`div:nth${_[n]<0?'-last':''}-of-type(${_[n]<0?-_[n]:_[n]})`)) && ((___ = __).click(), true)
  66. )
  67. clickMenu.msg && console.log(`${clickMenu.msgEnd?'✅ ':''}${clickMenu.msg}`)
  68. delete clickMenu.msg; delete clickMenu.msgEnd
  69. return [___, $$('[style^="position: absolute; z-index: 10"]')]
  70. }
  71.  
  72. function topbar(n) { return $(`.topbar > span:nth-child(1) > button:nth-child(${n})`) }
  73.  
  74.  
  75. function click(selector, instant) { instant === undefined ? $(selector).click() : setTimeout(()=>$(selector).click(),instant) }
  76. function onAppend(el, cb, {once, timeout}={}) {
  77. const mr = el._onAppend ??= new MutationObserver(function ([m]) { (cb(m)||once) && this.disconnect() })
  78. mr.observe(el, {childList:true, subtree:true})
  79. timeout && setTimeout(mr.disconnect, timeout)
  80. }
  81. function setParam(...inputs) { inputs.forEach(([input,val]) => { input.value = val; input.dispatchEvent(new Event('change')) }) }
  82. function dE(el, ev) { el.dispatchEvent(new Event(ev)) }
  83.  
  84. 'clickMenu setParam dE'.split(' ').forEach(f => unsafeWindow[`_${f}`] = eval(f))

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址