# Slider Object customization

**URL:** <https://forum.inductiveautomation.com/t/slider-object-customization/64005>\
**Category:** Ignition\
**Tags:** vision\
**Created:** [September 13, 2022, 1:09pm UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005 "2022-09-13T13:09:18Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![David\_Hargis](https://avatars.discourse-cdn.com/v4/letter/d/f04885/32.png) [@David\_Hargis](https://forum.inductiveautomation.com/u/David_Hargis)\
**Post date:** [September 13, 2022, 1:09pm UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/1 "2022-09-13T13:09:18Z")

</div>

Is there an easy way to modify the existing Vision slider component? I would like to change the blue track color, and make the slider object a pointed shape, instead of the circle. I was hoping there would be a different pointer object on the exchange, but did not find anything. Was going to try to script one/ build my own, but figured I would see if anybody had any recommendations first.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 13, 2022, 2:26pm UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/2 "2022-09-13T14:26:31Z")

</div>

Probably not; some more details in this thread:

> [@Color Slider Vision](https://forum.inductiveautomation.com/t/color-slider-vision/60297):
>
> Hi every one, Am not very good in java and everything and I got a problem using the slider o vision module. I want to change the color of every thing in that componant… Like actually in the designer you can change Foreground and Background but you dont have acces to the Track color,Thick color Back Track color and the shape and color of the slide properties. Do you know if there a way to edit that. Best regard, Gabriel

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 14, 2022, 7:04am UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/3 "2022-09-14T07:04:20Z")

</div>

I experimented with this, and I didn’t find it to difficult too do with layered shapes and scripting.  
Here is the result:

[https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/e/dea9105608f9f3c228e883e2de819a45cdf6fdb2.mp4](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/e/dea9105608f9f3c228e883e2de819a45cdf6fdb2.mp4)
  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/9/692202d2404cda9eb4897acba3bed62a84d2cab2.png)  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/e/1e5ec212cff4742a40eb38cbd7afb781bf3d350e.png)  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/1/f111eee7f93b373bfe17b3aa34204347e6e00d4a.png)

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 14, 2022, 7:20am UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/4 "2022-09-14T07:20:47Z")

</div>

Here is a tutorial for anybody who wants to replicate this:

- Create a container named CustomSliderComponent
- Use the rectangle tool to create a rectangle in the container named BackDrop that fills the entire container
- Add a slider to the container, name it CoreComponent, and resize the slider, so it completely fills the container
- Add a comma zero to the end of the background color to make the slider transparent:
- ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/2/825a90597476bd3330597a40bb6afe264e5028a0.png)
- Add four custom “Color” properties to the slider named backDropColor, leftOfPointerColor, rightOfPointerColor, and pointerColor. Then, set the colors to whatever you are going to want them to be
- Bind the BackDrop’s “Stroke Paint” and “Fill Paint” properties to the Core Component’s backDropColor custom property
- Use the rectangle tool again to draw a rectangle in the container that covers the entire slider, name it RightValues, and bind it’s “Stroke Paint” and “Fill Paint” properties to the rightOfPointerColor custom property of the CoreComponent:
- ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/e/ce12bb3a2210e16c9796c976931d2ba975e72dd0.png)
- Copy the RightValues rectangle, and paste a new rectangle directly on top of the copied rectangle. I recommend using Ctrl+P (Size and Position Dialog Box) to ensure that the new rectangle is exactly on top of the RightValues rectangle.
- Give this new rectangle the name “LeftValues” and bind its “Fill Paint” and “Stroke Paint” properties to the CoreComponent’s leftOfPointerColor custom property. Lastly, change the width of the LeftValues rectangle to approximately half it the width of the slider:
- ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/e/6e0c6445d0624f94c2c348adc7348547d4ec5506.png)
- Use the polygon tool to create a custom shape for the pointer within the container. Then, name the shape “Pointer” and bind its “Fill Paint” property to the “pointerColor” custom property of the CoreComponent:
- ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/7/173beafeb43f1d83f0b5f0ccee9ad06e67a1b850.png)
- The Project Browser should now look like this:
- ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/3/a31a21627ae6095818107dee8675d25d4aa3651c.png)
- Add this script the Pointer’s mouseDragged event handler:

```auto
abslutePointerWidth = event.source.relWidth*(event.source.parent.getComponent('BackDrop').getSize().getWidth()/event.source.parent.getComponent('BackDrop').relWidth)
if event.x > event.source.parent.getComponent('BackDrop').getSize().getWidth()-abslutePointerWidth:
	system.gui.transform(event.source, event.source.parent.getComponent('BackDrop').getSize().getWidth()-abslutePointerWidth)
elif event.x < 0:
	system.gui.transform(event.source, 0)
else:
	system.gui.transform(event.source, event.x)
event.source.parent.getComponent('CoreComponent').value = int(event.source.parent.getComponent('CoreComponent').minimum+((event.source.parent.getComponent('CoreComponent').maximum-event.source.parent.getComponent('CoreComponent').minimum)*event.source.relX)/(event.source.parent.getComponent('BackDrop').relWidth-event.source.relWidth))
event.source.parent.getComponent('LeftValues').relWidth = (event.source.parent.getComponent('BackDrop').relWidth-event.source.relWidth)-((event.source.parent.getComponent('BackDrop').relWidth-event.source.relWidth)-event.source.relX)

```

- Add this script to the CoreComponent’s mousePressed event handler:

```auto
if event.source.value > event.source.maximum:
	event.source.value = event.source.maximum
elif event.source.value < event.source.minimum:
	event.source.value = event.source.minimum	
event.source.parent.getComponent('Pointer').relX = ((event.source.parent.getComponent('BackDrop').relWidth-event.source.parent.getComponent('Pointer').relWidth)*(event.source.value-event.source.minimum))/(event.source.maximum-event.source.minimum)
event.source.parent.getComponent('LeftValues').relWidth = (event.source.parent.getComponent('BackDrop').relWidth-event.source.parent.getComponent('Pointer').relWidth)-((event.source.parent.getComponent('BackDrop').relWidth-event.source.parent.getComponent('Pointer').relWidth)-event.source.parent.getComponent('Pointer').relX)

```

I’ve tested this component in a published state with different window sizes and everything works. Here is the result:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/9/097a707404401da2d845be8183b018641538fc6d.png)

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/f/8f869fef01d944d0737c1b9324f319ef600834f9.png)

---

<div class="post-metadata">

**Author:** ![gpellicelli](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/gpellicelli/32/53466_2.png) [@gpellicelli](https://forum.inductiveautomation.com/u/gpellicelli)\
**Post date:** [September 19, 2022, 4:33pm UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/5 "2022-09-19T16:33:01Z")

</div>

I did a custom slider with mouse press action, tag value binding changed and Mouse dragged. I have start with the tutorial of @justinedwards.jle I just dont use the componant slider of igntion to do it. Its work fine but dont have the ability to use ‘snap to ticks’ and ‘defer update’ (This can be done for sure).The componant can be resize and use negative min and max value.

[https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/3/339e0222798ee39cf4bd929e1055751f7aed380c.mp4](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/3/339e0222798ee39cf4bd929e1055751f7aed380c.mp4)

[CustomSliderComponent.zip](https://forum.inductiveautomation.com/uploads/short-url/7vkabv2xJraduJkHTOkpoZObfi2.zip) (12.8 KB)

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 21, 2022, 12:59pm UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/6 "2022-09-21T12:59:47Z")

</div>

I like your use of a linear scale instead of an actual slider for the core component. It works quite well!

---

<div class="post-metadata">

**Author:** ![Ricardo\_javier\_reyes](https://avatars.discourse-cdn.com/v4/letter/r/e9bcb4/32.png) [@Ricardo\_javier\_reyes](https://forum.inductiveautomation.com/u/Ricardo_javier_reyes)\
**Post date:** [November 6, 2023, 11:32pm UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/7 "2023-11-06T23:32:04Z")

</div>

And how could I adapt this code if the slider is in a vertical position? I tried to adapt it, but I'm not very good with coding. Can you help me? Below, I show how I tried to adapt it.

```auto
abslutePointerHeight = event.source.relHeight * (event.source.parent.getComponent('BackDrop').getSize().getHeight() / event.source.parent.getComponent('BackDrop').relHeight)
if event.y > event.source.parent.getComponent('BackDrop').getSize().getHeight() - abslutePointerHeight:
    system.gui.transform(event.source, event.source.parent.getComponent('BackDrop').getSize().getHeight() - abslutePointerHeight)
elif event.y < 0:
    system.gui.transform(event.source, 0)
else:
    system.gui.transform(event.source, event.y)

event.source.parent.getComponent('CoreComponent').value = int(event.source.parent.getComponent('CoreComponent').minimum + ((event.source.parent.getComponent('CoreComponent').maximum - event.source.parent.getComponent('CoreComponent').minimum) * event.source.relY) / (event.source.parent.getComponent('BackDrop').relHeight - event.source.relHeight))

event.source.parent.getComponent('LeftValues').relHeight = (event.source.parent.getComponent('BackDrop').relHeight - event.source.relHeight) - ((event.source.parent.getComponent('BackDrop').relHeight - event.source.relHeight) - event.source.relY)

```

```auto
if event.source.value > event.source.maximum:
    event.source.value = event.source.maximum
elif event.source.value < event.source.minimum:
    event.source.value = event.source.minimum

event.source.parent.getComponent('Pointer').relX = ((event.source.parent.getComponent('BackDrop').relWidth - event.source.parent.getComponent('Pointer').relWidth) * (event.source.value - event.source.minimum)) / (event.source.maximum - event.source.minimum)

event.source.parent.getComponent('LeftValues').relWidth = (event.source.parent.getComponent('BackDrop').relWidth - event.source.parent.getComponent('Pointer').relWidth) - ((event.source.parent.getComponent('BackDrop').relWidth - event.source.parent.getComponent('Pointer').relWidth) - event.source.parent.getComponent('Pointer').relX)

```

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [November 7, 2023, 7:30am UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/8 "2023-11-07T07:30:27Z")

</div>

Way back when I initially worked on this, I hadn't yet developed [a reliable way to transform components within templates](https://forum.inductiveautomation.com/t/how-to-transform-a-component-inside-of-a-vision-template/80122/6), so I relied on additional shapes embedded in the component to get relative dimensions. The way I do this sort of thing now is much simpler.

Here is a reworked vertical version of @gpellicelli's scale for you to study:  
[customVerticalSlider.zip](https://forum.inductiveautomation.com/uploads/short-url/kZpfz447CmqGLVXXRIzHQlfSylQ.zip) (12.2 KB)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/e/cec1fc9a76b80e9c491e8820ae7c76495005214a.png)

---

<div class="post-metadata">

**Author:** ![Ricardo\_javier\_reyes](https://avatars.discourse-cdn.com/v4/letter/r/e9bcb4/32.png) [@Ricardo\_javier\_reyes](https://forum.inductiveautomation.com/u/Ricardo_javier_reyes)\
**Post date:** [November 7, 2023, 2:56pm UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/9 "2023-11-07T14:56:27Z")

</div>

Thank you very much for your help. I really appreciate it

---

<div class="post-metadata">

**Author:** ![Ricardo\_javier\_reyes](https://avatars.discourse-cdn.com/v4/letter/r/e9bcb4/32.png) [@Ricardo\_javier\_reyes](https://forum.inductiveautomation.com/u/Ricardo_javier_reyes)\
**Post date:** [November 7, 2023, 10:04pm UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/10 "2023-11-07T22:04:32Z")

</div>

I've been studying how CustomVerticalSlider works and I've understood some things, but not all. Right now, my knowledge still doesn't reach that level. I tried to adjust it to my need, which is to make the 'value' property bidirectional and be able to write to it from a numeric text field, but I was unsuccessful in trying to adapt it. Could you help me or give me a push to solve it?

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [November 8, 2023, 4:49am UTC](https://forum.inductiveautomation.com/t/slider-object-customization/64005/11 "2023-11-08T04:49:02Z")

</div>

It would be tricky to convert the way I scripted it. Basically, everything needs to be flipped around so the value drives the position instead of the position driving the value. That way, every movement of the pointer sets the value property, and then the propertyChange event handler can set the position.

...or the value can be set directly without the pointer being moved, and the propertyChange event handler will then set the position.

Basically, change this:

```auto
def getValueFromPosition(self, newPosition):
	# Get the min and max positions in pixels from the getMinMaxPositions custom method
	minPosition, maxPosition = self.getMinMaxPositions()
	
	# Get the min and max value custom property values from the template
	maxValue = self.parent.valueMax
	minValue = self.parent.valueMin
	
	# Determine how far newPosition is between minPosition and maxPosition as a fraction
	# Use a turnary operator to eliminate the possibility of dividing by zero
	ratio = ((newPosition - minPosition) / (maxPosition - minPosition)) if maxPosition != minPosition else 0
	
	# Scale the value to be between minValue and maxValue using the ratio
	scaledValue = maxValue - (ratio * (maxValue - minValue))
	
	# Set the new position custom property, so it will not need to be recalculated
	# ...by the propertyChange event handler that drives the transformations
	self.newPosition = newPosition
	
	# Assign the scaled value to the templates value property
	self.parent.value = scaledValue

```

to this:

```auto
def getPositionFromValue(self, newValue):
	# Get the min and max value custom property values from the template
	maxValue = self.parent.valueMax
	minValue = self.parent.valueMin
	
	# Get the min and max positions in pixels from the getMinMaxPositions custom method
	minPosition, maxPosition = self.getMinMaxPositions()
	
	# Determine how far the new value is between minPosition and maximum allowed value as a fraction
	# Use a turnary operator to eliminate the possibility of dividing by zero
	ratio = ((newValue - minValue) / (maxValue - minValue)) if maxValue != minValue else 0
	
	# Scale the value to be between minPosition and maxPosition using the ratio and return it as the newPosition for the pointer
	return maxPosition - (ratio * (maxPosition - minPosition))

```

Then, drive the transformation from the template's propertyChange event handler like this:

```auto
if event.propertyName == 'value':
	pointer = event.source.getComponent('Pointer')
	newPosition = pointer.getPositionFromValue(event.newValue)
	system.gui.transform(pointer, newY = newPosition)

```

In any case, I went ahead and updated the vertical slider, so it has the desired behavior. Here it is:  
[customVerticalSlider\_v1.1.zip](https://forum.inductiveautomation.com/uploads/short-url/qM25pAYZHbMErfDWqk3ucwqVMh1.zip) (13.0 KB)
