cocopon / tweakpane

:control_knobs: Compact GUI for fine-tuning parameters and monitoring value changes
https://tweakpane.github.io/docs/
MIT License
3.57k stars 90 forks source link

Download Link & File Input #353

Closed pspeter3 closed 2 years ago

pspeter3 commented 2 years ago

It would be nice if Tweakpane supported a Download Button and a File Input type. This would help with both importing and exporting the presets.

pspeter3 commented 2 years ago

I think the Download link would could be styled as the Button Blade but just requires rendering as HTMLAnchorElement instead with href and download attributes.

cocopon commented 2 years ago

Currently I don't have a plan to add these to the core because how to implement the feature depends on the people. Some people download/upload a file, some people copy/paste a log, and some people use LocalStorage.

You can implement it by using the plugin system: https://cocopon.github.io/tweakpane/plugins.html

pspeter3 commented 2 years ago

Got it. My primary use case was actually allowing the download of an image I generate. (I'm allowing people to edit the parameters of the image with Tweakpane). I'll checkout the plugins section.

cocopon commented 2 years ago

You can create a download button as below:

pane.addButton({
  title: "Download",
}).on("click", () => {
  const canvas = document.querySelector('canvas');
  const a = document.createElement("a");
  a.download = "capture.png";
  a.href = canvas.toDataURL();
  a.click();
});

https://codesandbox.io/s/tweakpane-playground-alga-l2z2o

bumbeishvili commented 1 year ago

If someone needs it, here is my code for achieving this:

  <!--  You will need to have input with type='file' somewhere, for opening a dialog -->
  <input type="file" style="display:none" id="fileInput" />

Here is a javascript code responsible for export & import. (I am using d3 in one place, but just for adding an event, you can use vanilla js for it)

// ----------------------    Export   ---------------------- 
const btnExport = pane.addButton({
        title: 'Download State',
        label: 'Export',   // optional
});

btnExport.on('click', function () {
        const state = pane.exportState();
        let exportObj = state;
        var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
        var downloadAnchorNode = document.createElement('a');
        downloadAnchorNode.setAttribute("href", dataStr);
        downloadAnchorNode.setAttribute("download", 'state' + ".json");
        document.body.appendChild(downloadAnchorNode); // required for firefox
        downloadAnchorNode.click();
        downloadAnchorNode.remove();
});

// ----------------------   Import. ---------------------- 
const btnImport = pane.addButton({
        title: 'Import State',
        label: 'Import',   // optional
});

btnImport.on('click', function () {
        let input = document.getElementById('fileInput');
        function onReaderLoad(event) {
                console.log(event.target.result);
                var obj = JSON.parse(event.target.result);
                pane.importState(obj);
                console.log('loaded file', obj)
        }

        d3.select(input).on('change.input', e => {
                const file = e.srcElement.files[0];
                var reader = new FileReader();
                reader.onload = onReaderLoad;
                reader.readAsText(file);
        })
        input.click();
});

https://github.com/cocopon/tweakpane/assets/6873202/5a4d4cec-86a4-4b56-bdd3-01428e869424