You are not logged in.
Pages: 1
Topic closed
What is the best way to create your own buttons in Inkscape?
I tried to use the existing example as a template in Inkscape but I was not very successful ... it is working but the layout/graphics are changed after uploading it to the webserver.
Last edited by scoobsalamander (2015-11-05 17:25:16)
Offline
Oops, I totally missed your post, sorry. Do you mean creating your own graphical objects which will work like buttons? Something like General/PushOnOff but with another face, right?
I'll post a tutorial here but I'll start with simple on/off indicator and advance to custom button afterwards, ok?
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
No problem...
Yes indeed, that's exactly what I meant.
I was trying to build a GUI for the heating control @ home but the WAF (Wife Acceptance Factor) of the original button was not high enough ;-) . Therefore I wanted to create my own buttons but all this SVG/HTML5 and javascript is more or less new to me so a little help is more than welcome.
An on/off indicator is nice to start with....(but isn't this already covered in the pool examples by using 'Group animation-color change'?)
thx
Last edited by scoobsalamander (2015-11-17 21:46:54)
Offline
OK, here is a step-by-step guide to create your own component in Inkscape. For starters we'll develop a simple indicator of a Boolean (logic) signal. In this case two circles, which will light up exclusively, based on a Boolean signal in the control algorithm. You could achieve the same functionality using the Group animations but our goal is to create a button, a component which is able to control. You cannot create control components using Group animations. And you cannot create active component without understanding the principles, which are best illustrated in passive components (indicators).
Open a blank document in Inkscape (without the "RexHMI Config" object)
Create a SVG illustration in Inkscape (two circles, as mentioned above, place them side by side)
Group the whole illustration (Ctrl+G) and save the file, see BlinkLR_src.svg for reference
Go to menu Extensions->RexHMI->Group Animation, tick Rotate and click OK
Go to menu Extensions->RexHMI->Group Animation, untick Rotate and click OK (by this you just wrapped the object and set internal properties which are necessary for the component to work)
Open the XML editor in Inkscape (Ctrl+Shift+X)
Find svg:g belonging to the newly created component (id="g4007" in the case of BlinkLR_src.svg file, it is inside the "g2990" group, which is the mentioned wrapper)
Drag this group to the root object svg:svg so that it resides inside the so-called root level
The remains of the original object (wrapper and also layer1) should be deleted - Delete node.
In the component being created change the value of the rexsvg:module ns0:module attribute from "GeneralComponent" to "BlinkLR"
Find svg:path of the left circle (id="path4005")
Add the rexsvg:module ns0:tag attribute manually and set it to "LeftCirc"
Find svg:path of the right circle (id="path3235")
Add the rexsvg:module ns0:tag attribute manually and set it to "RightCirc"
Find svg:title (id="title4104"), unfold it and change "Title" to "BlinkLRindicator"
Find svg:desc (id="desc4106"), unfold and enter the description of the parameters of the component:
{
"connections": {"STATUS": "$T_STATUS"},
"options": {"LeftColor": "#00ff00", "RightColor": "#ff0000"},
"metaData": {}
}
Check the code from previous step at www.jsonlint.com, the JSON syntax must be 100% valid
Close the XML editor
Click on the new component (select it) and go to Extensions->RexHMI->Edit Element - a configuration dialog should appear, just like in the case of standard elements from the library
Save the SVG file with the new component as "BlinkLR.svg", the name must correspond with the name from step 10 (the resulting SVG file is included in the MySvgLib.zip file for reference).
In the same folder create a subfolder "js"
Create a file "BlinkLR.js", the name must again correspond with step 10.
The .js file defines the animation and behavior of the object. It can contain something like this:
REX.UI.SVG.BlinkLR = function (svgElem, args) {
// Inherit from base component
var obj = Object.create(REX.UI.SVG.Component(svgElem, args));
// Store options for simple usage
var $opt = obj.options || {};
// Load options or default values
var LeftColor = $opt.LeftColor || "#ff0000";
var RightColor = $opt.RightColor || "#00ff00";
// Get SVG elements for manipulation
var lcirc = obj.getChildByTag("LeftCirc");
var rcirc = obj.getChildByTag("RightCirc");
// Add anonymous function as event listener. There are two events
// 'read' - it is called every time when item is read
// 'change' - called for the first time and every time item value is changed
obj.$c.STATUS.on('change', function onChange(itm) {
if (itm.getValue()) {
rcirc.setAttributeNS(null, "style", "fill-opacity:1.0; fill:" + RightColor + ";");
lcirc.setAttributeNS(null, "style", "fill-opacity:0.0; fill:" + LeftColor + ";");
} else {
rcirc.setAttributeNS(null, "style", "fill-opacity:0.0; fill:" + RightColor + ";");
lcirc.setAttributeNS(null, "style", "fill-opacity:1.0; fill:" + LeftColor + ";");
}
});
return obj;
};
When developing your components, use this code as a template. Respect the sytax of the file and remember that:
The first line must contain the correct name of the component (again step 10), thus: REX.UI.SVG.BlinkLR = function (svgElem, args)
Reading options must correspond with the options from step 16.
Searching objects in SVG (getChildByTag) must respect the naming from steps 12 and 14.
Function obj.$c.STATUS.on() must correspond with "connections" from step 16.
Function itm.getValue() returns the value of the signal in the REX control algorithm, just like you can see it e.g. in RexView - this value can be used for arbitrary animation.
The component is almost ready. You should have something like the MySvgLib.zip file contains.
To include the component in the exported HMI, you have to move the folder with the component and the JavaScript code to the C:\ProgramData\REX Controls\RexHMI\libs folder (name the folder e.g. MySvgLib).
Now create the HMI in Inkscape just like you would with the standard components and export the HMI. Use testHMI.zip to test the component I have developed.
Repeat the procedure for indicators of your taste. Always put the SVG file with the component to the MySvgLib folder as well as the corresponding .js file to the js subfolder.
Explore our components for inspiration.
BEWARE! - Your user libraries might get deleted when uninstalling/updating the RexHMI extension for Inkscape. Always have a backup!
Download links:
Hope this helps. Let me know if it works for you. Later we'll advance to active (control) components.
Last edited by jaroslav_sobota (2015-11-23 11:26:49)
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
First of all, a big thank you for another well explained tutorial.
I'll give it a try today and let you know how it went....
Offline
first attempt didn't work....
I noticed that I do not have an attribute called rexsvg:module. In my Inkscape object it is called ns0:module, did I missed something?
Here an the XML of the example with the rexsvg:tag......
Here the XML of my own created object but this one doesn't get the same tags as the example.
Last edited by scoobsalamander (2015-11-21 20:29:06)
Offline
Sorry, my fault. Use ns0:module and ns0:tag instead of rexsvg:module and rexsvg:tag. I have updated my previous post and the source files.
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
I had to copy the javascript from 'BlinkLR.js' into the existing file 'rex-ui-svg-general.js' to make it work. (adding the reference in the HTML file is also an option I guess but using the 'rex-ui-svg-general.js' file seems to be the standard way, correct...?)
The ns0:tags for the LeftCirc and RightCirc are also to be created manually because they are not automatically added during the wrapping process.
...but it is working now and I slowly start to understand how (more or less....)
ready for the next step.... ;-)
Offline
There is no need to modify the original libraries. As stated in step 24, create e.g. MySvgLib folder inside
C:\ProgramData\REX Controls\RexHMI\libs
Put the BlinkLR.svg file into this folder and the BlinkLR.js file inside a subfolder called js.
And yes, the ns0:tag attributes must be added, as stated in steps 12 and 14. I have added manually into my original post.
Let me know if it works.
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
A general overview is that you create some SVG graphics, you tag the parts which you want to animate and then you write a JavaScript which finds the tagged elements and modifies them based on the data read from the control algorithm. Hope this helps to improve your understanding.
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
That's what I did, but when exporting to html the reference to my own library is not automatically inserted into the index.html file.
Offline
Did you leave the Library Path field empty?
If yes, all libraries from C:\ProgramData\REX Controls\RexHMI\libs should be added automatically...
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
Offline
Please upload also your source SVG file if possible.
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
(don't mind my circles, they look like rectangles..... )
Offline
Everything is working fine, the only thing is that I have to include the library manually inside index.html
Offline
I can confirm your component is perfectly valid. However, I'm not able to replicate your bug...
Even if the generated index.html does not contain a link to the BlinkLR.js file, is the BlinkLR.js file included in the exported HMI/js folder?
Can you please try exporting the HMI with the following settings?
With this settings, is the link to BlinkLR.js present in the index.html file? Can you please upload the whole exported HMI?
Thanks!
PS Your rectangular circles are beautiful
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
I exported with the same settings as you described above but it looks like that the paths for the libraries are not exported. It's only when I leave the field empty that the index.html file contains the path to the libraries....
Offline
The export works as it should, except the fact that your library is ignored for some reason. With empty Library Path, all libraries from C:\ProgramData\REX Controls\RexHMI\libs are exported:
<script type="text/javascript" src="js/rex-ui-svg-general.js"></script>
<script type="text/javascript" src="js/rex-ui-svg-home.js"></script>
<script type="text/javascript" src="js/rex-ui-svg-hvac.js"></script>
When libraries are listed in Library Path, only the selected ones are included:
<script type="text/javascript" src="js/rex-ui-svg-general.js"></script>
In both cases, the line with your library should be included:
<script type="text/javascript" src="js/BlinkLR.js"></script>
However, it is ignored for some unknown reason and I do want to find out why. Thanks for your cooperation so far.
What Windows are you using?
What version of RexHMI extension are you using (Extensions->RexHMI->Version Info)?
Can you try running Inkscape as Administrator and do both exports once again?
Can you please zip the whole folder C:\ProgramData\REX Controls\RexHMI\libs as you have it at the moment and upload it here?
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
Yep, exactly. I can work around this issue but it would be nice that I can use my own libraries and that they are implemented automatically. (no rush as my own libraries do not exist yet... )
What Windows are you using? Windows 10 Pro
What version of RexHMI extension are you using (Extensions->RexHMI->Version Info)?version 0.7.185
Can you try running Inkscape as Administrator and do both exports once again? see below
Can you please zip the whole folder C:\ProgramData\REX Controls\RexHMI\libs as you have it at the moment and upload it here? Link to REX-Controls.zip
exported files as administrator :
exported HMI with path to libraries
exported HMI with empty field (no paths to libraries)
I think I did the conversion to Windows 10 when REXControl was already installed, maybe I should try to remove the complete installation and start all over with a fresh clean installation?
(FYI : I was not able to copy objects out of the library into my project when Inkscape was started as administrator. So I prepared a project as normal user and exported as administrator.)
Last edited by scoobsalamander (2015-11-26 09:08:42)
Offline
Thanks, now I understand. The problem is that you have your custom component in C:\ProgramData\REX Controls\RexHMI\libs\MySvgLib\BlinkLR. You have to move it one level up to the folder C:\ProgramData\REX Controls\RexHMI\libs\MySvgLib which is shown here:
Hope this is the problem. If you placed the component in the subfolder by mistake, then no problem. If some part of the tutorial convinced you to put the files in the subfolder, please let me know which one so I can make it more clear for other users.
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
....feel stupid again....sorry for wasting your time.
It's there now....thanks for the help!!
Last edited by scoobsalamander (2015-11-26 11:12:18)
Offline
Here is the second part of the tutorial. We'll create a simple button to control a Boolean signal and display its status. The best part is that you can create a button which is completely yours so it can match your style.
Open a blank document in Inkscape (without the "RexHMI Config" object).
Create an SVG illustration in Inkscape (a rectangle and a text, the text overlays the rectangle and stands for the label of the button).
Group the whole illustration (Ctrl+G) and save the file, see MyButton_src.svg.
Extensions->RexHMI->Group Animation, tick Rotate and click OK.
Extensions->RexHMI->Group Animation, untick Rotate and click OK (by this you just wrapped the object and set internal properties which are necessary for the component to work).
Open the XML editor in Inkscape (Ctrl+Shift+X).
Find svg:g belonging to the newly created component (id="g2993" in the case of MyButton_src.svg file, it is inside another group, which is the mentioned wrapper).
Drag this group to the root object svg:svg so that it resides inside the so-called root level.
The remains of the original object (wrapper and also layer1) should be deleted - Delete node.
In the component being created change the value of the ns0:module attribute from "GeneralComponent" to "MyButton".
Find svg:rect (the rectangle, id="rect2985")..
Add the ns0:tag attribute manually and set it to "ButtonRect".
Find svg:text (the text object, id="text2987"). Alternatively it also could be an svg:tspan object.
Add the ns0:tag attribute manually and set it to "Label".
Find svg:title (id="title3000"), unfold it and change "Title" to "ButtonElement".
Find svg:desc (id="desc3002"), unfold and enter the description of the parameters of the component:
{
"connections":{"RSTATUS":"$T_RSTATUS","WSTATUS":"$T_WSTATUS"},
"metaData":{},
"options":{"OffColor":"#ff8000","OnColor":"#008000","LabelOffColor":"#ffffff","LabelOnColor":"#ffffff","LabelOff":"OFF","LabelOn":"ON"}
}
Check the code from previous step at www.jsonlint.com, the JSON syntax must be 100% valid.
Close the XML editor.
Click on the new component (select it) and go to Extensions->RexHMI->Edit Element - a configuration dialog should appear, just like in the case of standard elements from the library.
Save the SVG file with the new component as "MyButton.svg", the name must correspond with the name from step 10 (the resulting SVG file is included in the MySvgLib.zip file for reference).
In the same folder create a subfolder "js".
Inside the "js" subfolder, create a file "MyButton.js", the name must correspond with step 10 again.
The .js file defines the animation and behavior of the object. It can contain something like this:
REX.UI.SVG.MyButton = function (svgElem, args) {
// Inherit from base component
var obj = Object.create(REX.UI.SVG.Component(svgElem, args));
// Store options for simple usage
var $opt = obj.options || {};
// Load options or default values
var OffColor = $opt.OffColor || "#ff8000";
var OnColor = $opt.OnColor || "#008000";
var LabelOffColor = $opt.LabelOffColor || "#ffffff";
var LabelOnColor = $opt.LabelOnColor || "#ffffff";
var LabelOff = $opt.LabelOff || "OFF";
var LabelOn = $opt.LabelOn || "ON";
// Get SVG elements for manipulation
var rect = obj.getChildByTag("ButtonRect");
var label = obj.getChildByTag("Label");
// This function changes current state of the button according to the
// value read from item.
function refreshState(itm){
if(itm.getValue()){ // Value is 'non zero' value
// Use jQuery to change fill style parameter
$(rect).css('fill',OnColor);
$(label).css('fill',LabelOnColor);
label.textContent = LabelOn;
}
else{ // Value is 'zero'
$(rect).css('fill',OffColor);
$(label).css('fill',LabelOffColor);
label.textContent = LabelOff;
}
}
// Every writable component should be synchronized with current state of the
// control system. Variable 'referesh_from' stores the value of readable connection (fallback to the writable connection)
var refresh_from = obj.$c.RSTATUS || obj.$c.WSTATUS;
refresh_from.on('change', refreshState);
// Create jQuery object from the button (parent of the rectangle element), then add new listener for 'mousedown' event
$(rect).parent().on('mousedown',function(evt){
// Prevent propagation of the event to the children of the target element
evt.preventDefault();
// Disable refreshing of the value to allow user to change input
// (e.q. Number in input, position of the slider, etc.)
refresh_from.disableRefresh = true;
// Process the parameters of the event.
if(evt.which === 1){ // Left mouse button
// Write some value to the writable connection
// Write number '1' immediately
obj.$c.WSTATUS.setValue(1,true);
}
// Enable refresh again
refresh_from.disableRefresh = false;
});
$(rect).parent().on('mouseup',function(evt){
// Prevent propagation of the event to the children of the target element
evt.preventDefault();
// Disable refreshing of the value to allow user to change input
// (e.q. Number in input, position of the slider, etc.)
refresh_from.disableRefresh = true;
// Process the parameters of the event.
if(evt.which === 1){ // Left mouse button
// Write some value to the writable connection
// Write number '0' immediately
obj.$c.WSTATUS.setValue(0,true);
}
// Enable refresh again
refresh_from.disableRefresh = false;
});
return obj;
};
When developing your components, use this code as a template. Respect the sytax of the file and remember that:
The first line must contain the correct name of the component (again step 10), thus: REX.UI.SVG.MyButton = function (svgElem, args)
Loading options must correspond with the options from step 16.
Searching objects in SVG (getChildByTag) must respect the naming from steps 12 and 14.
obj.$c.RSTATUS and obj.$c.WSTATUS must correspond with "connections" from step 16.
Function itm.getValue() returns the value of the signal in the REX control algorithm, just like you can see it e.g. in RexView - this value can be used for arbitrary animation.
The component is almost ready. You should have something like the MySvgLib-button.zip file contains.
To include the component in the exported HMI, you have to move the folder with the component and the JavaScript code to the C:\ProgramData\REX Controls\RexHMI\libs folder (name the folder e.g. MySvgLib).
Now create the HMI in Inkscape just like you would with the standard components and export the HMI. Use testHMI-button.zip to test the component I have developed.
Repeat the procedure for additional buttons of your taste. Always put the SVG file with the component to the MySvgLib folder as well as the corresponding .js file to the js subfolder.
Explore our components for inspiration.
BEWARE! - Your user libraries might get deleted when uninstalling/updating the RexHMI extension for Inkscape. Always have a backup!
Download links:
Hope this helps. Let me know if it works for you.
Monarco HAT for Raspberry Pi - Lightweight I/O for monitoring, archiving and control.
Raspberry Pi in industrial automation!
Offline
Hi, this does not work for me:
var obj = Object.create(REX.UI.SVG.Component(svgElem, args));
Instead, I had to use this:
var obj = new REX.UI.SVG.Component(svgElem,args);
Offline
Yes that is correct for the new version of the components, REX version > 2.50.1
Offline
Pages: 1
Topic closed