add a parameter adjustment panel #19
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
I tried using AI to add a parameter adjustment panel to the plugin, so that I could adjust the stylus optimization parameters myself and achieve a handwriting experience that suits me. In version 0.6.0, I easily generated a usable parameter adjustment panel, but in version 0.7.1, it always reports an error: “plugin siyuan-jsdraw-plugin onload error: TypeError: Cannot read properties of undefined (reading 'title')”. Below is the method provided by AI for adding the parameter adjustment panel. Could you please add a parameter adjustment panel that allows users to adjust their handwriting experience themselves? Thank you.
search:
module.exports=mh;
replace:
module.exports=mh; setTimeout(function(){ if(document.body){ var p=window.jsdrawParams=window.jsdrawParams||{}; p.Ua=p.Ua||{mass:.2,springConstant:200,frictionCoefficient:.5,maxPointDist:8,inertiaFraction:.9,minSimilarityToFinalize:0,velocityDecayFactor:.3}; p.tr=p.tr||{maxSpeed:5,maxRadius:12,minTimeSeconds:.5}; p.polylineWidthFactor=p.polylineWidthFactor||.55; p.lineMergeCosThreshold=p.lineMergeCosThreshold||.995; var b=document.createElement('div'); b.innerHTML='✎'; b.style.cssText='position:fixed; bottom:20px; right:20px; width:48px; height:48px; background:#2e8b57; color:white; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:28px; cursor:pointer; z-index:10000; box-shadow:0 2px 8px rgba(0,0,0,0.3);'; b.title='手写参数调节'; document.body.appendChild(b); var pa=document.createElement('div'); pa.style.cssText='position:fixed; bottom:80px; right:20px; width:280px; background:#1e1e2f; color:#eee; border-radius:12px; padding:16px; font-family:sans-serif; z-index:10001; box-shadow:0 4px 16px rgba(0,0,0,0.5); display:none; flex-direction:column; gap:12px; backdrop-filter:blur(8px); border:1px solid #4a4a5a;'; document.body.appendChild(pa); function addSlider(l,o,k,min,max,step,fl){var w=document.createElement('div'); w.style.display='flex'; w.style.flexDirection='column'; w.style.gap='4px'; var s=document.createElement('span'); s.textContent=l+': '+p[o][k]; s.style.fontSize='13px'; var i=document.createElement('input'); i.type='range'; i.min=min; i.max=max; i.step=step; i.value=p[o][k]; i.oninput=function(){var v=fl?parseFloat(this.value):parseInt(this.value); p[o][k]=v; s.textContent=l+': '+v; }; w.appendChild(s); w.appendChild(i); pa.appendChild(w); } function addSimpleSlider(l,k,min,max,step,fl){var w=document.createElement('div'); w.style.display='flex'; w.style.flexDirection='column'; w.style.gap='4px'; var s=document.createElement('span'); s.textContent=l+': '+p[k]; s.style.fontSize='13px'; var i=document.createElement('input'); i.type='range'; i.min=min; i.max=max; i.step=step; i.value=p[k]; i.oninput=function(){var v=fl?parseFloat(this.value):parseInt(this.value); p[k]=v; s.textContent=l+': '+v; }; w.appendChild(s); w.appendChild(i); pa.appendChild(w); } pa.innerHTML='
Thanks for the suggestion! Just to understand it better, could you also provide the patch you used on v0.6.0? I want to test it to see exactly what you're trying to achieve.
Search1:
$a={kind:Fi.IntertialStabilizer,mass:.4,springConstant:100,frictionCoefficient:.28,maxPointDist:10,inertiaFraction:.75,minSimilarityToFinalize:0,velocityDecayFactor:.1}Replace1:
$a={kind:Fi.IntertialStabilizer,mass:.4,springConstant:100,frictionCoefficient:.28,maxPointDist:10,inertiaFraction:.75,minSimilarityToFinalize:0,velocityDecayFactor:.1};const polylineStabilizerDefaults={mass:.4,springConstant:100,frictionCoefficient:.28,maxPointDist:10,inertiaFraction:.75,minSimilarityToFinalize:0,velocityDecayFactor:.1}Search2:
Ks={maxSpeed:8.5,maxRadius:11,minTimeSeconds:.5}Replace2:
Ks={maxSpeed:8.5,maxRadius:11,minTimeSeconds:.5};const polylineAutocorrectDefaults={maxSpeed:8.5,maxRadius:11,minTimeSeconds:.5}Search3:
class Nn extends be{constructor(e,n,i){super(e.notifier,n),this.editor=e,this.builder=null,this.lastPoint=null,this.startPoint=null,this.currentDeviceType=null,this.currentPointerId=null,this.shapeAutocompletionEnabled=!1,this.pressureSensitivityEnabled=!0Replace3:
class Nn extends be{constructor(e,n,i){super(e.notifier,n),this.editor=e,this.builder=null,this.stabilizerOptions=Object.assign({},polylineStabilizerDefaults,i.stabilizerOptions||{}),this.autocorrectOptions=Object.assign({},polylineAutocorrectDefaults,i.autocorrectOptions||{}),this.lastPoint=null,this.startPoint=null,this.currentDeviceType=null,this.currentPointerId=null,this.shapeAutocompletionEnabled=!1,this.pressureSensitivityEnabled=!0Search4:
n?this.setInputMapper(null):this.setInputMapper(new ri(this.editor.viewport))Replace4:
n?this.setInputMapper(null):this.setInputMapper(new ri(this.editor.viewport,this.stabilizerOptions))Search5:
this.stationaryDetector=new js(n,Ks,a=>this.autocorrectShape(a))Replace5:
this.stationaryDetector=new js(n,this.autocorrectOptions,a=>this.autocorrectShape(a))Search6:
getPressureSensitivityEnabled(){return this.pressureSensitivityEnabled}Replace6:
getPressureSensitivityEnabled(){return this.pressureSensitivityEnabled}setStabilizerOptions(e){Object.assign(this.stabilizerOptions,e);if(this.getInputMapper()){var t=this.getInputMapper();t&&t instanceof ri&&(this.setHasStabilization(!1),this.setHasStabilization(!0))}}setAutocorrectOptions(e){Object.assign(this.autocorrectOptions,e)}Search7:
this.setupChangeListeners()}Replace7:
this.setupChangeListeners();setTimeout(()=>{createPolylineFloatingButton(this.editor)},500)}Search8:
module.exports=ah;Replace8:
function createPolylineFloatingButton(e){if(!e)return;var t=localStorage.getItem("jsdraw_polyline_params");var n=t?JSON.parse(t):{stabilizer:polylineStabilizerDefaults,autocorrect:polylineAutocorrectDefaults,sampleMultiplier:0.65,simplifyThreshold:0.997};window.__polylineOptions={sampleMultiplier:n.sampleMultiplier,simplifyThreshold:n.simplifyThreshold};function i(){var r=e.toolController.getMatchingTools(Nn).find(function(e){return e.getStrokeFactory()===ei});if(r){r.setStabilizerOptions(n.stabilizer);r.setAutocorrectOptions(n.autocorrect);r.setStrokeFactory(ei)}}i();var o=document.createElement("div");o.style.position="fixed";o.style.bottom="20px";o.style.right="20px";o.style.zIndex="9999";var a=document.createElement("button");a.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path fill="white" d="M480-480Zm0 400q-133 0-226.5-93.5T160-400q0-133 93.5-226.5T480-720q133 0 226.5 93.5T800-400q0 133-93.5 226.5T480-80Zm0-80q100 0 170-70t70-170q0-100-70-170T480-640q-100 0-170 70t-70 170q0 100 70 170t170 70Zm-40-240v-80h80v80h-80Zm0-120v-160h80v160h-80Z"/></svg>';a.style.padding="8px";a.style.background="#3f51b5";a.style.color="#fff";a.style.border="none";a.style.borderRadius="50%";a.style.width="48px";a.style.height="48px";a.style.cursor="pointer";a.title="折线笔参数";o.appendChild(a);var l=document.createElement("div");l.style.display="none";l.style.position="absolute";l.style.bottom="50px";l.style.right="0";l.style.background="#fff";l.style.border="1px solid #ccc";l.style.padding="10px";l.style.borderRadius="4px";l.style.width="300px";l.style.boxShadow="0 2px 10px rgba(0,0,0,0.2)";l.innerHTML="<h4 style='margin-top:0'>折线笔参数</h4>";function s(r,c,f,u,d,p){var m=document.createElement("div");m.style.marginBottom="8px";var v=document.createElement("label");v.textContent=r+":";v.style.display="inline-block";v.style.fontSize="12px";v.style.width="50%";var g=document.createElement("span");g.textContent=d;g.style.fontSize="12px";g.style.marginLeft="8px";var h=document.createElement("input");h.type="range";h.min=c;h.max=f;h.step=String(u);h.value=d;h.style.width="100%";h.addEventListener("input",function(){var w=parseFloat(this.value);g.textContent=w;if(p==="stabilizer"){n.stabilizer[r]=w}else if(p==="autocorrect"){n.autocorrect[r]=w}else if(p==="sampleMultiplier"){n.sampleMultiplier=w;window.__polylineOptions.sampleMultiplier=w}else if(p==="simplifyThreshold"){n.simplifyThreshold=w;window.__polylineOptions.simplifyThreshold=w}i();localStorage.setItem("jsdraw_polyline_params",JSON.stringify(n))});m.appendChild(v);m.appendChild(g);m.appendChild(h);return m}l.appendChild(s("质量",0,2,0.1,n.stabilizer.mass,"stabilizer"));l.appendChild(s("弹性系数",10,500,10,n.stabilizer.springConstant,"stabilizer"));l.appendChild(s("阻尼系数",0,1,0.05,n.stabilizer.frictionCoefficient,"stabilizer"));l.appendChild(s("最大点距",1,30,0.5,n.stabilizer.maxPointDist,"stabilizer"));l.appendChild(s("惯性分数",0.5,1,0.01,n.stabilizer.inertiaFraction,"stabilizer"));l.appendChild(s("速度衰减",0,1,0.05,n.stabilizer.velocityDecayFactor,"stabilizer"));l.appendChild(s("自动更正-最大速度",1,30,0.5,n.autocorrect.maxSpeed,"autocorrect"));l.appendChild(s("自动更正-最大半径",2,50,1,n.autocorrect.maxRadius,"autocorrect"));l.appendChild(s("自动更正-静置时间(秒)",0.1,3,0.05,n.autocorrect.minTimeSeconds,"autocorrect"));l.appendChild(s("采样步长乘数",0.2,2,0.05,n.sampleMultiplier,"sampleMultiplier"));l.appendChild(s("简化共线阈值",0.9,1,0.001,n.simplifyThreshold,"simplifyThreshold"));o.appendChild(l);a.addEventListener("click",function(){l.style.display=l.style.display==="none"?"block":"none"});document.body.appendChild(o)}module.exports=ah;Search9:
const ei=to((s,e)=>{const n=e.getSizeOfPixelOnCanvas()*.65;return new Cl(s,n,e)})Replace9:
const ei=to((s,e)=>{var t=window.__polylineOptions||{};var i=t.sampleMultiplier||0.65;var r=t.simplifyThreshold||0.997;var n=e.getSizeOfPixelOnCanvas()*i;var o=new Cl(s,n,e);o.simplifyThreshold=r;return o})Search10:
>.997&&(this.parts.pop(),this.lastPoint=this.lastLineSegment.p1),this.parts.push(Replace10:
>(this.simplifyThreshold||0.997)&&(this.parts.pop(),this.lastPoint=this.lastLineSegment.p1),this.parts.push(Please refer to this. this modification is base on version 0.6.0
I have drafted an implementation. Please test me and let me know if it works well for you.
This is an experimental build and it might break. You can revert to the stable version at any time by uninstalling the plugin and re-installing it from the SiYuan marketplace, your drawings will NOT be lost.
For the sake of consistency with the design language, the writing options are not in a floating icon, they can be accessed from within the editor, using the "advanced options" (⚙️) icon in the navbar.
Download the build here. Replace the entire
index.jsof the plugin with this file.That’s exactly the kind of functionality I’m looking for—works great. However, the plugin does tend to crash occasionally.
VM324 plugin:siyuan-jsdraw-plugin:56 Blocked script execution in 'http://127.0.0.1:57089/stage/build/app/?v=1779328554710' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
eval @ VM324 plugin:siyuan-jsdraw-plugin:56
VM324 plugin:siyuan-jsdraw-plugin:513 Non-finite zoom (NaN) detected. Resetting the viewport. This was likely caused by division by zero.
eval @ VM324 plugin:siyuan-jsdraw-plugin:513
VM324 plugin:siyuan-jsdraw-plugin:56 Blocked script execution in 'http://127.0.0.1:57089/stage/build/app/?v=1779328554710' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
eval @ VM324 plugin:siyuan-jsdraw-plugin:56
VM324 plugin:siyuan-jsdraw-plugin:513 Non-finite zoom (NaN) detected. Resetting the viewport. This was likely caused by division by zero.
eval @ VM324 plugin:siyuan-jsdraw-plugin:513
main.4e8d325c5c6854d1f240.js:8082 plugin siyuan-jsdraw-plugin onload error: TypeError: Cannot read properties of undefined (reading 'title')
at Ch.populateSettingMenu (plugin:siyuan-jsdraw-plugin:754:14245)
at new Ch (plugin:siyuan-jsdraw-plugin:754:12024)
at Ih.startConfig (plugin:siyuan-jsdraw-plugin:761:3458)
at async Ih.onload (plugin:siyuan-jsdraw-plugin:761:542)
at async sw (main.4e8d325c5c6854d1f240.js:8082:684)
at async Bg (main.4e8d325c5c6854d1f240.js:8082:182)
“Download the build here. Replace the entire index.js of the plugin with this file.”
It seems that ever since I started using this script, js-draw crashes every time a sync happens.
Sorry for not getting back to you sooner, I was busy with other things. I have entirely rewritten the logic, and it seems to be much more stable from my tests.
For now, you can download the pre-release from here (though the stability is not guaranteed); I hope to publish a fully-tested stable release with all these features within the next few days.
Thank you for updating the plugin.
However, in the new version's settings panel, no matter how I adjust the parameters, I can't find a configuration that feels right for Chinese handwriting input. So I ended up modifying the
index.jsfile directly — I changede.getSizeOfPixelOnCanvas() * 0.65toe.getSizeOfPixelOnCanvas() * 0.08, and changed.997to.999. With these changes and the "stabilization" feature turned off, I find the handwriting experience much better for Chinese characters.Unfortunately, these two values are not exposed in the new version's parameter adjustment panel.😂
Thanks for the feedback. I was actually noticing some weird behavior myself on my new tablet, and I think that the parameters you have changed might help me as well.
I will investigate this further as soon as I have some free time, and if this works as a solution I will surely include in future releases.
Thank you!
Nowadays, most styli have built-in native smoothing for handwriting, so many of them can deliver a great writing experience without any additional stroke optimization. Could you please consider adding an option to disable all stroke optimizations and display the raw input directly? Thank you! @massivebox
Please test this build of the plugin. I have improved several things by forking js-draw entirely and editing its code directly.
I have increased the sample rate of inputs and removed the quantization of coordinates, so now drawing even with stroke smoothing should feel much better.
Even before this edit, we did not apply any optimization to writing, as long as Stabilization was disabled. But due to these two issues with quantization and sample rate, I can understand why you would think some poorly executed algorithm was in place.
Let me know how it works for you.
I'm waiting to release it because I'm worried these fixes (as well as others I have not mentioned) might degrade the performance on lower-end devices, or make whiteboards consume more storage space. I will test more when I have some free time, then release it to the public.
After trying it out, the handwriting experience on my device is excellent — it's fantastic, really great!!!
Additional suggestions:
2. When opened in dialog mode, the top bar of the window cannot be dragged to move it.3. Could you add a full‑screen feature? When writing with the stylus, it's easy to accidentally tap the taskbar buttons on the Windows PC. So could you add a full‑screen mode that covers all buttons and anything else that might cause accidental touches, so that users can write with the stylus without worry?@massivebox