MS Paint MS Paint ที่สมบูรณ์แบบพิกเซลที่สมบูรณ์แบบและอื่น ๆ ... ลองดู! จากนั้นเข้าร่วมเซิร์ฟเวอร์ Discord เพื่อแชร์ศิลปะของคุณ!
JS Paint จะสร้างเครื่องมือและเมนู MS Paint ทุกครั้งและแม้แต่คุณสมบัติที่ไม่ค่อยมีใครรู้จักไปสู่ความซื่อสัตย์ในระดับสูง
รองรับธีมประเภทไฟล์เพิ่มเติมและคุณสมบัติการเข้าถึงเช่นโหมดจ้องตาและการรู้จำเสียงพูด
อ่าใช่สีเก่าดี ไม่ใช่อันที่มีริบบิ้นหรือ skeuomorphic ใหม่ที่มีอินเทอร์เฟซที่สามารถใช้เวลาเกือบครึ่งหน้าจอ (และไม่ใช่สีที่ใหม่กว่า 3D)
Windows 95, 98 และ XP เป็นปีสีทองของสี คุณมีกล่องเครื่องมือและกล่องสีสีเบื้องหน้าและสีพื้นหลังและนั่นคือทั้งหมดที่คุณต้องการ
สิ่งที่เรียบง่าย
แต่เราต้องการยกเลิกการกระทำมากกว่าสามครั้ง เราต้องการแก้ไขภาพที่โปร่งใส เราไม่สามารถใช้สีเก่าได้
นั่นคือเหตุผลที่ฉันทำสี JS ฉันต้องการนำสีเก่า ๆ ที่ดีมาสู่ยุคสมัยใหม่
คุณสมบัติการแก้ไข:
การปรับปรุงเบ็ดเตล็ด:
ยังมีบางสิ่งที่มีเครื่องมือ see todo.md
การรองรับคลิปบอร์ดเต็มรูปแบบในเว็บแอปต้องใช้เบราว์เซอร์ที่รองรับ Async Clipboard API W/ Images คือ Chrome 76+ ในเวลาที่เขียน
ในเบราว์เซอร์อื่น ๆ คุณยังสามารถคัดลอกด้วย Ctrl+C ตัดด้วย Ctrl+X และวางด้วย Ctrl+V แต่ข้อมูลที่คัดลอกมาจาก JS Paint สามารถวางลงในอินสแตนซ์อื่น ๆ ของ JS Paint เท่านั้น สามารถวางรูปภาพภายนอกได้
ซึ่งแตกต่างจาก MS Paint คุณสามารถใช้ แก้ไข> เลิกทำ เพื่อเปลี่ยนสีหรือลดคุณภาพจากการประหยัด สิ่งนี้ไม่ได้ยกเลิกการบันทึกไฟล์ แต่อนุญาตให้คุณบันทึกในรูปแบบอื่นด้วยคุณภาพที่สูงขึ้นโดยใช้ ไฟล์> บันทึกเป็น
แนะนำให้ประหยัดตาม PNG เนื่องจากให้ขนาดไฟล์ขนาดเล็กในขณะที่ยังคงคุณภาพเต็ม
ส่วนขยายไฟล์ | ชื่อ | อ่าน | เขียน | อ่านจานสี | เขียนจาน |
---|---|---|---|---|---|
.png | png | ||||
.BMP, .DIB | บิตแมปขาวดำ | ||||
.BMP, .DIB | บิตแมปสี 16 สี | ||||
.BMP, .DIB | 256 บิตแมปสี | ||||
.BMP, .DIB | บิตแมป 24 บิต | N/A | N/A | ||
.tif, .tiff, .dng, .cr2, .Nef | TIFF (โหลดหน้าแรก) | ||||
PDF (โหลดหน้าแรก) | |||||
.webp | เว็บป | ||||
. gif | GIF | ||||
.jpeg, .jpg | jpeg | N/A | N/A | ||
.SVG | SVG (ขนาดเริ่มต้นเท่านั้น) | ||||
.ico | ICO (ขนาดเริ่มต้นเท่านั้น) |
ความสามารถที่ทำเครื่องหมายไว้ในขณะนี้อยู่ที่เบราว์เซอร์เพื่อรองรับหรือไม่ หาก "เขียน" ถูกทำเครื่องหมายด้วยรูปแบบจะปรากฏในแบบเลื่อนลงประเภทไฟล์ แต่อาจไม่ทำงานเมื่อคุณพยายามบันทึก สำหรับการเปิดไฟล์ดูตารางสนับสนุนรูปแบบรูปภาพเบราว์เซอร์ของ Wikipedia สำหรับข้อมูลเพิ่มเติม
ความสามารถที่ทำเครื่องหมายด้วยอาจจะมาเร็ว ๆ นี้และ n/a หมายความว่าไม่สามารถใช้ได้
"Read Palette" หมายถึงการโหลดสีลงในกล่องสีโดยอัตโนมัติ (จากภาพสีที่จัดทำดัชนี) และ "เขียน Palette" หมายถึงการเขียนภาพสีที่จัดทำดัชนี
ด้วย สี> บันทึกสี และ สี> รับสีที่ คุณสามารถบันทึกและโหลดสีในรูปแบบที่แตกต่างกันมากมายเพื่อเข้ากันได้กับโปรแกรมที่หลากหลาย
หากคุณต้องการเพิ่มการรองรับจานสีที่กว้างขวางไปยังแอปพลิเคชันอื่นฉันได้ทำฟังก์ชั่นนี้เป็นห้องสมุด: anypalette.js
ส่วนขยายไฟล์ | ชื่อ | โปรแกรม | อ่าน | เขียน |
---|---|---|---|---|
.เพื่อน | จานสี riff | MS Paint สำหรับ Windows 95 และ Windows NT 4.0 | ||
.gpl | จานสี GIMP | Gimp, Inkscape, Krita, Kolourpaint, Scribus, Cinepaint, MyPaint | ||
. ACO | Adobe Color Swatch | Adobe Photoshop | ||
.ase | Adobe Swatch Exchange | Adobe Photoshop, Indesign และ Illustrator | ||
.txt | Paint.net Palette | Paint.net | ||
.กระทำ | ตารางสี adobe | Adobe Photoshop และ Illustrator | ||
.pal, .psppalette | Paint Shop Pro Palette | Paint Shop Pro (JASC Software / Corel) | ||
.hpl | จานบ้าน | Allaire Homesite / Macromedia Coldfusion | ||
.cs | Colorchemer | สตูดิโอ Colorschemer | ||
.เพื่อน | สตาร์คราฟต์พาเล็ต | สตาร์คราฟต์ | ||
.wpe | จานสี Starcraft Terrain | สตาร์คราฟต์ | ||
.Sketchpalette | ภาพร่าง | ร่าง | ||
.SPL | จานสี Skencil | Skencil (เดิมชื่อ Sketch) | ||
.soc | สี staroffice | Staroffice, OpenOffice, Libreoffice | ||
. สี | คอลเลกชันสี Kolourpaint | Kolourpaint | ||
. สี | โทนสีพลาสมาเดสก์ท็อป | KDE พลาสมาเดสก์ท็อป | ||
.ธีม | ธีม Windows | Windows Desktop | ||
. Themepack | ธีม Windows | Windows Desktop | ||
.css, .scss, .styl | สไตล์ชีท | เว็บเบราว์เซอร์ / หน้าเว็บ | ||
.html, .svg, .js | ไฟล์ข้อความใด ๆ ที่มีสี CSS | เว็บเบราว์เซอร์ / หน้าเว็บ |
มีโหมดขาวดำที่มี ลวดลาย แทนสีในจานสีซึ่งคุณสามารถไปจาก ภาพ> แอตทริบิวต์ ...
คุณสามารถลากกล่องสีและกล่องเครื่องมือไปรอบ ๆ หากคุณคว้าพวกเขาไปทางที่ถูกต้อง คุณสามารถลากออกไปในหน้าต่างเล็ก ๆ คุณสามารถเชื่อมต่อหน้าต่างกลับไปด้านข้างโดยดับเบิลคลิกที่แถบชื่อเรื่อง
นอกเหนือจากสีเบื้องหน้าคลิกซ้ายและสีพื้นหลังคลิกขวาแล้วยังมีสีที่สามที่คุณสามารถเข้าถึงได้โดยถือ Ctrl ในขณะที่คุณวาด มันเริ่มต้นโดยไม่มีสีดังนั้นคุณจะต้องถือ Ctrl และเลือกสีก่อน สิ่งที่แฟนซีเกี่ยวกับสล็อตสีนี้คือคุณสามารถกดและปล่อย Ctrl เพื่อสลับสี ขณะวาด
คุณสามารถใช้การแปลงภาพเช่นพลิก/หมุนยืด/เอียงหรือกลับ (ในเมนูภาพ) ไม่ว่าจะเป็นภาพทั้งหมดหรือการเลือก ลองเขียนลวก ๆ ด้วยเครื่องมือเลือกแบบฟรีจากนั้นทำ รูปภาพ> Invert
เคล็ดลับและกลเม็ดเหล่านี้จากการสอนสำหรับ MS Paint ยังทำงานใน JS Paint:
JS Paint สามารถติดตั้งเป็นแอปพลิเคชันเว็บแบบก้าวหน้า (PWA) แม้ว่ามันจะยังไม่ทำงานออฟไลน์ มองหาพรอมต์การติดตั้งในแถบที่อยู่
คุณสมบัติ PWA:
คุณสมบัติที่ขาดหายไป:
ฉันได้สร้างมันขึ้นเป็นแอพเดสก์ท็อปด้วยอิเล็กตรอนและอิเล็กตรอน คุณสามารถดาวน์โหลดได้จากหน้าเผยแพร่
คุณสมบัติแอพอิเล็กตรอน:
jspaint path/to/file.png
ในเทอร์มินัลeditor_window.on("close")
การเรียก preventDefault
และอาจเป็นคุณสมบัติ แต่ต้องแสดง/โฟกัสหน้าต่างโคลน repo
ติดตั้ง node.js หากคุณไม่มีให้เปิดพรอมต์คำสั่ง / เทอร์มินัลในไดเรกทอรีโครงการ
เรียกใช้ npm run lint
เพื่อตรวจสอบข้อผิดพลาดในการสะกด, พิมพ์ข้อผิดพลาด, ปัญหาสไตล์รหัสและปัญหาอื่น ๆ
เรียกใช้ npm run format
เพื่อแก้ไขปัญหาการจัดรูปแบบโดยอัตโนมัติหรือ npx eslint --fix
เพื่อแก้ไขปัญหาที่สามารถติดตั้งอัตโนมัติได้ทั้งหมด
กฎการจัดรูปแบบได้รับการกำหนดค่าสำหรับความเข้ากันได้กับรูปแบบในตัวของ VS Code
เรียกใช้ npm test
เพื่อเรียกใช้การทดสอบที่ใช้เบราว์เซอร์ด้วย Cypress (เริ่มต้นและเรียกใช้การทดสอบช้าน่าเสียดาย)
npm run accept
การยอมรับการเปลี่ยนแปลงภาพใด ๆ สิ่งนี้น่าเสียดายที่การทดสอบทั้งหมดอีกครั้งแทนที่จะยอมรับผลลัพธ์ของการทดสอบก่อนหน้านี้ดังนั้นคุณสามารถจบลงด้วยผลลัพธ์ที่แตกต่างจากการทดสอบก่อนหน้านี้ หากคุณใช้เดสก์ท็อป GitHub คุณสามารถดูภาพต่าง ๆ ในสี่โหมดที่แตกต่างกัน
หากต้องการเปิด Cypress UI ให้ npm run test:start-server
จากนั้น npm run cy:open
พร้อมกันพร้อมกัน
การทดสอบยังทำงานในการรวมอย่างต่อเนื่องกับ Travis CI
หลังจากที่คุณติดตั้งการพึ่งพาด้วย npm i
ให้ใช้ npm run dev
เพื่อเริ่มต้นเซิร์ฟเวอร์การโหลดสด
ตรวจสอบให้แน่ใจว่ารูปแบบการเลย์เอาต์ใด ๆ ที่สำคัญไปใน layout.css
เมื่ออัปเดต layout.css
เวอร์ชันขวาไปซ้ายของสไตล์ชีทจะถูกสร้างขึ้นโดยใช้ RTLCSS
คุณควรทดสอบเค้าโครง RTL โดยการเปลี่ยนภาษาเป็นภาษาอาหรับหรือภาษาฮีบรู ไปที่ ความพิเศษ> ภาษา> العربية หรือ עבית
ดูคำสั่งควบคุมสำหรับวิธีการควบคุมเค้าโครง RTL
มีงาน Launch Code VS สำหรับการแนบกับ Chrome สำหรับการดีบัก ดู .vscode/launch.json
สำหรับคำแนะนำการใช้งาน
npm i
npm run electron:start
มีการรวมอิเล็กตรอนเพื่อให้คุณสามารถใช้ F5 / Ctrl+R เพื่อโหลดซ้ำและ F12 / Ctrl+Shift+I เพื่อเปิด Devtools
คุณสามารถสร้างเพื่อการผลิตด้วย npm run electron:make
มีงานเรียกใช้รหัส VS สำหรับการดีบักกระบวนการหลักของอิเล็กตรอน สำหรับกระบวนการเรนเดอร์คุณสามารถใช้ chrome devtools ฝังตัว
JS Paint สามารถปรับใช้ได้โดยใช้เว็บเซิร์ฟเวอร์ปกติ
ไม่จำเป็นต้องรวบรวม
ทางเลือกคุณสามารถตั้งค่าเซิร์ฟเวอร์ CORS Anywhere สำหรับการโหลดภาพจากเว็บหากคุณวาง URL ลงในสี JS หรือใช้คุณสมบัติ #load:<URL>
ที่มีรูปภาพที่ไม่ได้อยู่ในโดเมนเดียวกัน
โดยค่าเริ่มต้นจะใช้อินสแตนซ์ CORS Anywhere ที่ตั้งค่าให้ทำงานกับ jspaint.app
เป็นโฮสต์ฟรีบน Heroku และคุณสามารถตั้งค่าอินสแตนซ์ของคุณเองและกำหนดค่าให้ทำงานกับโดเมนของคุณเอง
คุณจะต้องค้นหาและแทนที่ https://jspaint-cors-proxy.herokuapp.com
ด้วย URL อินสแตนซ์ของคุณเอง
การสนับสนุนผู้เล่นหลายคนในปัจจุบันอาศัย Firebase ซึ่งไม่ใช่ซอฟต์แวร์โอเพนซอร์ส
คุณสามารถสร้างอินสแตนซ์ฐานข้อมูล Firebase Realtime และแก้ไข sessions.js
ของ JS Paint.js เพื่อชี้ไปที่มันแทนที่ config
ที่ส่งผ่านไปยัง initializeApp
ด้วย config จากคอนโซล Firebase เมื่อคุณตั้งค่าแอปพลิเคชันเว็บ
แต่โหมดผู้เล่นหลายคนนั้นมีราคาต่ำมาก มันควรจะถูกแทนที่ด้วยสิ่งที่โอเพ่นซอร์สปลอดภัยมากขึ้นมีประสิทธิภาพมากขึ้นและมีความแข็งแกร่งมากขึ้น
เพิ่มสิ่งนี้ลงใน HTML ของคุณ:
< iframe src =" https://jspaint.app " width =" 100% " height =" 100% " > </ iframe >
คุณสามารถโหลดภาพจาก URL โดยเพิ่ม #load:<URL>
ไปยัง URL
< iframe src =" https://jspaint.app#load:https://jspaint.app/favicon.ico " width =" 100% " height =" 100% " > </ iframe >
หากคุณต้องการควบคุม JS Paint วิธีบันทึก/โหลดไฟล์หรือเข้าถึงผืนผ้าใบโดยตรงมี API ที่ไม่เสถียร
ก่อนอื่นคุณต้องโคลน repo ดังนั้นคุณสามารถชี้ iframe
ไปยังสำเนาในพื้นที่ของคุณ
สำเนาของ JS Paint จะต้องโฮสต์บนเว็บเซิร์ฟเวอร์เดียวกันกับหน้าบรรจุหรือโดยเฉพาะอย่างยิ่งจะต้องแชร์ต้นกำเนิดเดียวกัน
การมีสำเนาในพื้นที่ยังหมายความว่าสิ่งต่าง ๆ จะไม่แตกหักเมื่อใดก็ตามที่ API เปลี่ยนไป
หาก JS Paint ถูกโคลนไปยังโฟลเดอร์ที่เรียกว่า jspaint
ซึ่งอาศัยอยู่ในโฟลเดอร์เดียวกันกับหน้าเว็บที่คุณต้องการฝังอยู่ในนั้นคุณสามารถใช้สิ่งนี้ได้:
< iframe src =" jspaint/index.html " id =" jspaint-iframe " width =" 100% " height =" 100% " > </ iframe >
ถ้ามันอาศัยอยู่ที่อื่นคุณอาจต้องเพิ่ม ../
เพื่อเริ่มต้นเส้นทางเพื่อขึ้นไปในระดับ ตัวอย่างเช่น src="../../apps/jspaint/index.html"
นอกจากนี้คุณยังสามารถใช้ URL ที่แน่นอนเช่น src="https://example.com/cool-apps/jspaint/index.html"
คุณสามารถแทนที่กล่องโต้ตอบการบันทึกและเปิดไฟล์ด้วย systemHooks
API ของ JS Paint
< script >
var iframe = document . getElementById ( "jspaint-iframe" ) ;
var jspaint = iframe . contentWindow ;
// Wait for systemHooks object to exist (the iframe needs to load)
waitUntil ( ( ) => jspaint . systemHooks , 500 , ( ) => {
// Hook in
jspaint . systemHooks . showSaveFileDialog = async ( { formats , defaultFileName , defaultPath , defaultFileFormatID , getBlob , savedCallbackUnreliable , dialogTitle } ) => { ... } ;
jspaint . systemHooks . showOpenFileDialog = async ( { formats } ) => { ... } ;
jspaint . systemHooks . writeBlobToHandle = async ( save_file_handle , blob ) => { ... } ;
jspaint . systemHooks . readBlobFromHandle = async ( file_handle ) => { ... } ;
} ) ;
// General function to wait for a condition to be met, checking at regular intervals
function waitUntil ( test , interval , callback ) {
if ( test ( ) ) {
callback ( ) ;
} else {
setTimeout ( waitUntil , interval , test , interval , callback ) ;
}
}
</ script >
หยดแสดงเนื้อหาของไฟล์ในหน่วยความจำ
ที่จับไฟล์เป็นสิ่งที่สามารถระบุไฟล์ได้ คุณจะได้เป็นเจ้าของแนวคิดนี้และกำหนดวิธีการระบุไฟล์ อาจเป็นอะไรก็ได้จากดัชนีไปยังอาร์เรย์ไปจนถึงรหัสไฟล์ Dropbox ไปยัง URL IPFS ไปยังเส้นทางไฟล์ มันอาจเป็นประเภทใดก็ได้หรืออาจจะต้องเป็นสตริงฉันลืม
เมื่อคุณมีแนวคิดเกี่ยวกับการจับไฟล์คุณสามารถใช้ตัวเลือกไฟล์โดยใช้ตะขอระบบและฟังก์ชั่นในการอ่านและเขียนไฟล์
สั่งการ | ตะขอที่ใช้ |
---|---|
ไฟล์> บันทึกเป็น | systemHooks.showSaveFileDialog จากนั้นเมื่อเลือกไฟล์ systemHooks.writeBlobToHandle |
ไฟล์> เปิด | systemHooks.showOpenFileDialog จากนั้นเมื่อเลือกไฟล์ systemHooks.readBlobFromHandle |
ไฟล์> บันทึก | systemHooks.writeBlobToHandle (หรือเหมือนกับ ไฟล์> บันทึกราวกับ ว่ายังไม่มีไฟล์เปิด) |
แก้ไข> คัดลอกไปที่ | systemHooks.showSaveFileDialog จากนั้นเมื่อเลือกไฟล์ systemHooks.writeBlobToHandle |
แก้ไข> วางจาก | systemHooks.showOpenFileDialog จากนั้นเมื่อเลือกไฟล์ systemHooks.readBlobFromHandle |
ไฟล์> ตั้งค่าเป็นวอลล์เปเปอร์ (กระเบื้อง) | systemHooks.setWallpaperTiled ถ้ากำหนดแล้ว systemHooks.setWallpaperCentered หากกำหนดไว้อื่น ๆ เช่นเดียวกับ ไฟล์> บันทึกเป็น |
ไฟล์> ตั้งค่าเป็นวอลล์เปเปอร์ (กึ่งกลาง) | systemHooks.setWallpaperCentered ถ้ากำหนดอื่น ๆ เช่นเดียวกับ ไฟล์> บันทึกเป็น |
ความพิเศษ> แสดงประวัติเป็น gif | เหมือนกับ ไฟล์> บันทึกเป็น |
สี> บันทึกสี | เหมือนกับ ไฟล์> บันทึกเป็น |
สี> รับสี | เหมือนกับ ไฟล์> เปิด |
ในการเริ่มต้นแอปด้วยไฟล์ที่โหลดสำหรับการแก้ไขให้รอให้แอปโหลดจากนั้นเรียกใช้ systemHooks.readBlobFromHandle
ด้วยที่จับไฟล์และบอกให้แอปโหลด File BLOB นั้น
const file_handle = "initial-file-to-load" ;
systemHooks . readBlobFromHandle ( file_handle ) . then ( file => {
if ( file ) {
contentWindow . open_from_file ( file , file_handle ) ;
}
} , ( error ) => {
// Note: in some cases, this handler may not be called, and instead an error message is shown by readBlobFromHandle directly.
contentWindow . show_error_message ( `Failed to open file ${ file_handle } ` , error ) ;
} ) ;
นี่คือเงอะงะและในอนาคตอาจมีพารามิเตอร์สตริงแบบสอบถามเพื่อโหลดไฟล์เริ่มต้นโดยมือจับ (หมายเหตุถึงตัวเอง: จะต้องรอให้ระบบของคุณต้องลงทะเบียนอย่างใดอย่างหนึ่ง)
มีพารามิเตอร์สตริงแบบสอบถามอยู่แล้วที่จะโหลดจาก URL:
< iframe src =" https://jspaint.app?load:SOME_URL_HERE " > </ iframe >
แต่สิ่งนี้จะไม่ตั้งค่าที่จับไฟล์สำหรับการบันทึก
คุณสามารถกำหนดสองฟังก์ชั่นเพื่อตั้งค่าวอลล์เปเปอร์ซึ่งจะใช้โดย ไฟล์> ตั้งค่าเป็นวอลล์เปเปอร์ (กระเบื้อง) และ ไฟล์> ตั้งค่าเป็นวอลล์เปเปอร์ (กึ่งกลาง)
systemHooks.setWallpaperTiled
= (canvas) => { ... };
systemHooks.setWallpaperCentered
= (canvas) => { ... };
หากคุณกำหนดเฉพาะ systemHooks.setWallpaperCentered
JS Paint จะพยายามเดาขนาดของหน้าจอและกระเบื้องภาพโดยใช้มันโดยเรียกใช้ฟังก์ชัน systemHooks.setWallpaperCentered
หากคุณไม่ได้ระบุ systemHooks.setWallpaperCentered
JS Paint จะเริ่มต้นเพื่อบันทึกไฟล์ ( <original file name> wallpaper.png
) โดยใช้ systemHooks.showSaveFileDialog
และ systemHooks.writeBlobToHandle
นี่คือตัวอย่างเต็มรูปแบบที่รองรับวอลล์เปเปอร์ที่กำหนดเองแบบถาวรเป็นพื้นหลังในหน้าบรรจุ:
const wallpaper = document . querySelector ( "body" ) ; // or some other element
jspaint . systemHooks . setWallpaperCentered = ( canvas ) => {
canvas . toBlob ( ( blob ) => {
setDesktopWallpaper ( blob , "no-repeat" , true ) ;
} ) ;
} ;
jspaint . systemHooks . setWallpaperTiled = ( canvas ) => {
canvas . toBlob ( ( blob ) => {
setDesktopWallpaper ( blob , "repeat" , true ) ;
} ) ;
} ;
function setDesktopWallpaper ( file , repeat , saveToLocalStorage ) {
const blob_url = URL . createObjectURL ( file ) ;
wallpaper . style . backgroundImage = `url( ${ blob_url } )` ;
wallpaper . style . backgroundRepeat = repeat ;
wallpaper . style . backgroundPosition = "center" ;
wallpaper . style . backgroundSize = "auto" ;
if ( saveToLocalStorage ) {
const fileReader = new FileReader ( ) ;
fileReader . onload = ( ) => {
localStorage . setItem ( "wallpaper-data-url" , fileReader . result ) ;
localStorage . setItem ( "wallpaper-repeat" , repeat ) ;
} ;
fileReader . onerror = ( ) => {
console . error ( "Error reading file (for setting wallpaper)" , file ) ;
} ;
fileReader . readAsDataURL ( file ) ;
}
}
// Initialize the wallpaper from localStorage, if it exists
try {
const wallpaper_data_url = localStorage . getItem ( "wallpaper-data-url" ) ;
const wallpaper_repeat = localStorage . getItem ( "wallpaper-repeat" ) ;
if ( wallpaper_data_url ) {
fetch ( wallpaper_data_url ) . then ( response => response . blob ( ) ) . then ( file => {
setDesktopWallpaper ( file , wallpaper_repeat , false ) ;
} ) ;
}
} catch ( error ) {
console . error ( error ) ;
}
มันเป็นการเรียกซ้ำเล็กน้อยขออภัย; มันอาจจะทำได้ง่ายกว่า เช่นเดียวกับการใช้ URL ข้อมูล (ที่จริงฉันคิดว่าฉันต้องการใช้ URL blob เพียงเพื่อไม่ให้ผู้ตรวจการ DOM ด้วย URL ยาวสุด ๆ ซึ่งเป็นข้อผิดพลาดของ Devtools UX จริง ๆ
คุณสามารถโหลดไฟล์ที่มีขนาดที่ต้องการ ไม่มี API พิเศษสำหรับเรื่องนี้ในขณะนี้
ดูการโหลดไฟล์ในตอนแรก
คุณสามารถเปลี่ยนธีมโดยทางโปรแกรม:
var iframe = document . getElementById ( "jspaint-iframe" ) ;
var jspaint = iframe . contentWindow ;
jspaint . set_theme ( "modern.css" ) ;
แต่สิ่งนี้จะทำลายการตั้งค่าของผู้ใช้
เมนู อาหารพิเศษ> ชุดรูปแบบ จะยังคงทำงานอยู่ แต่การตั้งค่าจะไม่คงอยู่เมื่อโหลดหน้าใหม่
ในอนาคตอาจมีพารามิเตอร์สตริงแบบสอบถามเพื่อระบุธีมเริ่มต้น นอกจากนี้คุณยังสามารถแยก JSpaint เพื่อเปลี่ยนธีมเริ่มต้น
คล้ายกับธีมคุณสามารถลองเปลี่ยนภาษาโดยทางโปรแกรม:
var iframe = document . getElementById ( "jspaint-iframe" ) ;
var jspaint = iframe . contentWindow ;
jspaint . set_language ( "ar" ) ;
แต่สิ่งนี้จะ ขอให้ผู้ใช้โหลดแอปพลิเคชันใหม่ เพื่อเปลี่ยนภาษา
เมนู พิเศษ> ภาษา จะยังคงทำงานอยู่ แต่ผู้ใช้จะต้องเปลี่ยนภาษาทุกครั้งที่โหลดหน้าใหม่
ในอนาคตอาจมีพารามิเตอร์สตริงแบบสอบถามเพื่อระบุภาษาเริ่มต้น นอกจากนี้คุณยังสามารถแยก JSpaint เพื่อเปลี่ยนภาษาเริ่มต้น
ยังไม่รองรับ คุณสามารถแยก JSpaint และเพิ่มเมนูของคุณเอง
ด้วยการเข้าถึงผืนผ้าใบคุณสามารถใช้ตัวอย่างสดของภาพวาดของคุณเช่นการอัปเดตพื้นผิวในเอ็นจิ้นเกมแบบเรียลไทม์
var iframe = document . getElementById ( "jspaint-iframe" ) ;
// contentDocument here refers to the webpage loaded in the iframe, not the image document loaded in jspaint.
// We're just reaching inside the iframe to get the canvas.
var canvas = iframe . contentDocument . querySelector ( ".main-canvas" ) ;
ขอแนะนำให้ ไม่ ใช้สิ่งนี้สำหรับการโหลดเอกสารเนื่องจากจะไม่เปลี่ยนชื่อเอกสารหรือรีเซ็ตประวัติ UNDO/REDO เหนือสิ่งอื่นใด ใช้ open_from_file
แทน
หากคุณต้องการสร้างปุ่มหรือ UI อื่น ๆ เพื่อทำสิ่งต่าง ๆ กับเอกสารคุณควร (อาจ) ทำให้มันไม่สามารถทำได้ มันง่ายมากเพียงแค่ปิดการกระทำของคุณในการโทรไป undoable
var iframe = document . getElementById ( "jspaint-iframe" ) ;
var jspaint = iframe . contentWindow ;
var icon = new Image ( ) ;
icon . src = "some-folder/some-image-15x11-pixels.png" ;
jspaint . undoable ( {
name : "Seam Carve" ,
icon : icon , // optional
} , function ( ) {
// do something to the canvas
} ) ;
systemHooks.showSaveFileDialog({ formats, defaultFileName, defaultPath, defaultFileFormatID, getBlob, savedCallbackUnreliable, dialogTitle })
กำหนดฟังก์ชั่นนี้เพื่อแทนที่กล่องโต้ตอบบันทึกเริ่มต้น สิ่งนี้ใช้สำหรับการบันทึกภาพรวมถึงไฟล์พาเล็ตและภาพเคลื่อนไหว
ข้อโต้แย้ง:
formats
: อาร์เรย์ของวัตถุที่แสดงประเภทของไฟล์พร้อมคุณสมบัติต่อไปนี้:formatID
: สตริงที่ระบุรูปแบบที่ไม่ซ้ำกัน (อาจเหมือนกับ mimeType
)mimeType
(ไม่บังคับ): ประเภทสื่อที่กำหนดรูปแบบไฟล์เช่น "image/png"
(รูปแบบจานสีไม่มีคุณสมบัตินี้)name
: ชื่อรูปแบบไฟล์เช่น "WebP"
nameWithExtensions
: ชื่อรูปแบบไฟล์ตามด้วยรายการส่วนขยายเช่น "TIFF (*.tif;*.tiff)"
extensions
: อาร์เรย์ของส่วนขยายไฟล์ไม่รวม DOT ด้วยส่วนขยายที่ต้องการก่อนเช่น ["bmp", "dib"]
defaultFileName
(ไม่บังคับ): ชื่อไฟล์ที่แนะนำเช่น "Untitled.png"
หรือชื่อของเอกสารเปิดdefaultPath
(ไม่บังคับ): ที่จับไฟล์สำหรับเอกสารที่เปิดดังนั้นคุณสามารถบันทึกลงในโฟลเดอร์เดียวกันได้อย่างง่ายดาย การเรียกชื่อผิด: นี่อาจไม่ใช่เส้นทาง แต่ขึ้นอยู่กับวิธีที่คุณกำหนดมือจับไฟล์defaultFileFormatID
(ไม่บังคับ): formatID
ของรูปแบบไฟล์ที่จะเลือกโดยค่าเริ่มต้นasync function getBlob(formatID)
: ฟังก์ชั่นที่คุณเรียกเพื่อรับไฟล์ในรูปแบบหนึ่งที่รองรับ ต้องใช้ formatID
และส่งคืน Promise
ที่แก้ไขด้วย Blob
ที่แสดงเนื้อหาไฟล์เพื่อบันทึกfunction savedCallbackUnreliable({ newFileName, newFileFormatID, newFileHandle, newBlob })
(ไม่บังคับ): ฟังก์ชั่นที่คุณเรียกเมื่อผู้ใช้บันทึกไฟล์ newBlob
ควรมาจาก getBlob(newFileFormatID)
dialogTitle
(ไม่บังคับ): ชื่อเรื่องสำหรับกล่องโต้ตอบบันทึก หมายเหตุการผกผันของการควบคุมที่นี่: JS Paint เรียกฟังก์ชัน systemHooks.showSaveFileDialog
จากนั้นคุณเรียกฟังก์ชั่น getBlob
ของ JS Paint เมื่อ getBlob
แก้ไขแล้วคุณสามารถเรียกฟังก์ชัน savedCallbackUnreliable
ซึ่งกำหนดโดย JS Paint (หวังว่าฉันจะสามารถชี้แจงเรื่องนี้ได้ในอนาคต)
นอกจากนี้โปรดทราบว่าฟังก์ชั่นนี้รับผิดชอบในการบันทึกไฟล์ไม่ใช่แค่เลือกตำแหน่งบันทึก คุณสามารถใช้ฟังก์ชั่น systemHooks.writeBlobToHandle
ของคุณอีกครั้งหากเป็นประโยชน์
systemHooks.showOpenFileDialog({ formats })
กำหนดฟังก์ชั่นนี้เพื่อแทนที่กล่องโต้ตอบเปิดเริ่มต้น สิ่งนี้ใช้สำหรับการเปิดรูปภาพและจานสี
ข้อโต้แย้ง:
formats
: เหมือนกับ systemHooks.showSaveFileDialog
โปรดทราบว่าฟังก์ชั่นนี้มีหน้าที่รับผิดชอบในการโหลดเนื้อหาของไฟล์ไม่ใช่แค่เลือกไฟล์ คุณสามารถใช้ฟังก์ชั่น systemHooks.readBlobFromHandle
ของคุณอีกครั้งหากเป็นประโยชน์
systemHooks.writeBlobToHandle(fileHandle, blob)
กำหนดฟังก์ชั่นนี้เพื่อบอก JS Paint วิธีการบันทึกไฟล์
ข้อโต้แย้ง:
fileHandle
: การจัดการไฟล์ตามที่กำหนดโดยระบบของคุณแสดงถึงไฟล์ที่จะเขียนblob
: Blob
ที่แสดงเนื้อหาไฟล์เพื่อบันทึกผลตอบแทน:
Promise
ที่แก้ไขด้วย true
หากไฟล์ถูกบันทึกสำเร็จอย่างแน่นอน false
หากเกิดข้อผิดพลาดหรือผู้ใช้ยกเลิกหรือ undefined
หากไม่ทราบว่าไฟล์นั้นถูกบันทึกสำเร็จเช่นเดียวกับกรณีที่มีการดาวน์โหลดไฟล์ด้วย <a href="..." download="...">
สัญญาไม่ควรปฏิเสธ ข้อผิดพลาดควรได้รับการจัดการโดยแสดงข้อความแสดงข้อผิดพลาดและส่งคืน false
systemHooks.readBlobFromHandle(fileHandle)
กำหนดฟังก์ชั่นนี้เพื่อบอก JS Paint วิธีโหลดไฟล์
ข้อโต้แย้ง:
fileHandle
: การจัดการไฟล์ตามที่กำหนดโดยระบบของคุณแสดงถึงไฟล์ที่จะอ่านจาก systemHooks.setWallpaperTiled(canvas)
กำหนดฟังก์ชั่นนี้เพื่อบอก JS Paint วิธีการตั้งค่าวอลล์เปเปอร์ ดูชุดรวมเป็นวอลล์เปเปอร์สำหรับตัวอย่าง
ข้อโต้แย้ง:
canvas
: HTMLCanvasElement
พร้อมรูปภาพเพื่อตั้งค่าเป็นวอลล์เปเปอร์ systemHooks.setWallpaperCentered(canvas)
กำหนดฟังก์ชั่นนี้เพื่อบอก JS Paint วิธีการตั้งค่าวอลล์เปเปอร์ ดูชุดรวมเป็นวอลล์เปเปอร์สำหรับตัวอย่าง
ข้อโต้แย้ง:
canvas
: HTMLCanvasElement
พร้อมรูปภาพเพื่อตั้งค่าเป็นวอลล์เปเปอร์ undoable({ name, icon }, actionFunction)
ใช้สิ่งนี้เพื่อทำให้การกระทำไม่สามารถทำได้
ฟังก์ชั่นนี้ใช้ภาพรวมของผืนผ้าใบและสถานะอื่น ๆ จากนั้นเรียกใช้ฟังก์ชัน actionFunction
มันสร้างรายการในประวัติศาสตร์เพื่อให้สามารถยกเลิกได้
ข้อโต้แย้ง:
name
: ชื่อสำหรับการกระทำเช่น "Brush"
หรือ "Rotate Image 270°"
icon
(ไม่บังคับ): Image
ที่จะแสดงในหน้าต่างประวัติ ขอแนะนำให้เป็น 15x11 พิกเซลactionFunction
: ฟังก์ชั่นที่ไม่มีข้อโต้แย้งและปรับเปลี่ยนผืนผ้าใบ show_error_message(message, [error])
ใช้สิ่งนี้เพื่อแสดงกล่องโต้ตอบข้อความแสดงข้อผิดพลาดโดยเลือกพร้อมรายละเอียดข้อผิดพลาดที่ขยายได้
ข้อโต้แย้ง:
message
: ข้อความธรรมดาที่จะแสดงในกล่องโต้ตอบerror
(ไม่บังคับ): วัตถุ Error
ที่จะแสดงในกล่องโต้ตอบยุบโดยค่าเริ่มต้นในส่วน "รายละเอียด" ที่ขยายได้ open_from_file(blob, source_file_handle)
ใช้สิ่งนี้เพื่อโหลดไฟล์ลงในแอพ
ข้อโต้แย้ง:
blob
: วัตถุ Blob
ที่แสดงไฟล์เพื่อโหลดsource_file_handle
: ที่จับไฟล์ ที่เกี่ยวข้อง สำหรับไฟล์ตามที่กำหนดโดยระบบของคุณขออภัยสำหรับ API ที่เล่นโวหาร API เป็นของใหม่และบางส่วนของมันยังไม่ได้รับการออกแบบเลย นี่เป็นเพียงการแฮ็คที่ฉันต้องพึ่งพาการเอื้อมมือไปที่ Internals of JS Paint เพื่อโหลดไฟล์ ฉันตัดสินใจที่จะจัดทำเอกสารว่าเป็น API เวอร์ชันแรกเนื่องจากฉันต้องการ changelog เมื่ออัพเกรดการใช้งานของฉันต่อไป
set_theme(theme_file_name)
ใช้สิ่งนี้เพื่อเปลี่ยนรูปลักษณ์ของแอปพลิเคชัน
ข้อโต้แย้ง:
theme_file_name
: ชื่อของไฟล์ธีมที่จะโหลดหนึ่งใน:"classic.css"
: ธีม Windows98"dark.css"
: The Dark Theme"modern.css"
: ธีมที่ทันสมัย"winter.css"
: ธีมฤดูหนาวเทศกาล"occult.css"
: ธีมซาตาน set_language(language_code)
คุณสามารถใช้สิ่งนี้เพื่อเปลี่ยนภาษาของแอปพลิเคชัน แต่จริงๆแล้วมันจะแสดงให้ผู้ใช้เปลี่ยนภาษาเนื่องจากแอปพลิเคชันจำเป็นต้องโหลดซ้ำเพื่อใช้การเปลี่ยนแปลง และถ้าบทสนทนานั้นไม่ได้อยู่ในภาษาที่ถูกต้องพวกเขาอาจจะสับสน
ข้อโต้แย้ง:
language_code
: รหัสภาษาที่จะใช้เช่น "en"
สำหรับภาษาอังกฤษ, "zh"
สำหรับภาษาจีนดั้งเดิม, "zh-simplified"
สำหรับภาษาจีนง่าย ๆ ฯลฯ API จะเปลี่ยนไปมาก แต่การเปลี่ยนแปลงจะถูกบันทึกไว้ในการเปลี่ยนแปลง
ไม่เพียง แต่เป็นประวัติศาสตร์ของการเปลี่ยนแปลง แต่เป็นคู่มือการย้าย/การอัพเกรด
สำหรับข่าวโครงการทั่วไปคลิก Extras> ข่าวโครงการ ในแอพ
JS Paint เป็นซอฟต์แวร์ฟรีและโอเพ่นซอร์สที่ได้รับอนุญาตภายใต้ใบอนุญาต MIT ที่ได้รับอนุญาต