René's URL Explorer Experiment


Title: New Styling for Sliders · Issue #19256 · matplotlib/matplotlib · GitHub

Open Graph Title: New Styling for Sliders · Issue #19256 · matplotlib/matplotlib

X Title: New Styling for Sliders · Issue #19256 · matplotlib/matplotlib

Description: Problem I've never loved the way Matplotlib Slider widgets look (and per jupyter-widgets/ipywidgets#3025 (comment) I am apparently not alone). However, beyond that I think that the current way the slider widgets are drawn introduces two ...

Open Graph Description: Problem I've never loved the way Matplotlib Slider widgets look (and per jupyter-widgets/ipywidgets#3025 (comment) I am apparently not alone). However, beyond that I think that the current way the ...

X Description: Problem I've never loved the way Matplotlib Slider widgets look (and per jupyter-widgets/ipywidgets#3025 (comment) I am apparently not alone). However, beyond that I think that the current way ...

Opengraph URL: https://github.com/matplotlib/matplotlib/issues/19256

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"New Styling for Sliders","articleBody":"\u003c!--\r\nWelcome! Thanks for thinking of a way to improve Matplotlib.\r\n\r\n\r\nBefore creating a new feature request please search the issues for relevant feature requests.\r\n--\u003e\r\n\r\n### Problem\r\nI've never loved the way Matplotlib Slider widgets look (and per https://github.com/jupyter-widgets/ipywidgets/issues/3025#issuecomment-756263435 I am apparently not alone). However, beyond that I think that the current way the slider widgets are drawn introduces two issue that hamper usability.\r\n\r\n1. There is no clear handle for the user to grab\r\n2. No visual feedback that you've grabbed the slider\r\n\r\n`\u003cspeculation\u003e` More broadly I suspect that most people's expectation of what a slider UI element will look like is strongly shaped by how they look on the web. So if Matplotlib sliders look more similar to web sliders then they will be more natural for users. `\u003c/speculation\u003e`\r\n\r\n### Proposed Solution\r\nSomething to the effect of this:\r\n\r\n\u003cdetails\u003e\r\n \u003csummary\u003e\u003cb\u003escript with new slider definition + an example\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n```python\r\nimport numpy as np\r\nfrom matplotlib.widgets import SliderBase\r\nfrom matplotlib import _api\r\nimport matplotlib.patches as mpatches\r\nfrom matplotlib import transforms\r\n\r\nclass newSlider(SliderBase):\r\n    cnt = _api.deprecated(\"3.4\")(property(# Not real, but close enough.\r\n        lambda self: len(self._observers.callbacks['changed'])))\r\n    observers = _api.deprecated(\"3.4\")(property( lambda self: self._observers.callbacks['changed']))\r\n\r\n    def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,\r\n                 closedmin=True, closedmax=True, slidermin=None,\r\n                 slidermax=None, dragging=True, valstep=None,\r\n                 orientation='horizontal', *, initcolor='r',s=10, **kwargs):\r\n        super().__init__(ax, orientation, closedmin, closedmax,\r\n                                 valmin, valmax, valfmt, dragging, valstep)\r\n\r\n        if slidermin is not None and not hasattr(slidermin, 'val'):\r\n            raise ValueError(\r\n                f\"Argument slidermin ({type(slidermin)}) has no 'val'\")\r\n        if slidermax is not None and not hasattr(slidermax, 'val'):\r\n            raise ValueError(\r\n                f\"Argument slidermax ({type(slidermax)}) has no 'val'\")\r\n        self.slidermin = slidermin\r\n        self.slidermax = slidermax\r\n        valinit = self._value_in_bounds(valinit)\r\n        if valinit is None:\r\n            valinit = valmin\r\n        self.val = valinit\r\n        self.valinit = valinit\r\n\r\n        ax.axis('off')\r\n        self.dot, = ax.plot([valinit],[.5], 'o', markersize=s, color='C0')\r\n        trans = transforms.blended_transform_factory(\r\n            ax.transData, ax.transAxes)\r\n        self.rect = mpatches.Rectangle((valmin, .25), width=valinit-valmin, height=.5, transform=trans,\r\n                              color='C0', alpha=0.75)\r\n        self.above_rect = mpatches.Rectangle((valinit, .25), width=valmax-valinit, height=.5, transform=trans,\r\n                              color='grey', alpha=0.5)\r\n        ax.add_patch(self.rect)\r\n        ax.add_patch(self.above_rect)\r\n\r\n        self.label = ax.text(-0.02, 0.5, label, transform=ax.transAxes,\r\n                             verticalalignment='center',\r\n                             horizontalalignment='right')\r\n\r\n        self.valtext = ax.text(1.02, 0.5, self._format(valinit),\r\n                               transform=ax.transAxes,\r\n                               verticalalignment='center',\r\n                               horizontalalignment='left')\r\n\r\n        self.set_val(valinit)\r\n\r\n\r\n    def _format(self, val):\r\n        \"\"\"Pretty-print *val*.\"\"\"\r\n        if self.valfmt is not None:\r\n            return self.valfmt % val\r\n        else:\r\n            _, s, _ = self._fmt.format_ticks([self.valmin, val, self.valmax])\r\n            # fmt.get_offset is actually the multiplicative factor, if any.\r\n            return s + self._fmt.get_offset()\r\n        \r\n    def _value_in_bounds(self, val):\r\n        \"\"\"Makes sure *val* is with given bounds.\"\"\"\r\n        val = self._stepped_value(val)\r\n\r\n        if val \u003c= self.valmin:\r\n            if not self.closedmin:\r\n                return\r\n            val = self.valmin\r\n        elif val \u003e= self.valmax:\r\n            if not self.closedmax:\r\n                return\r\n            val = self.valmax\r\n\r\n        if self.slidermin is not None and val \u003c= self.slidermin.val:\r\n            if not self.closedmin:\r\n                return\r\n            val = self.slidermin.val\r\n\r\n        if self.slidermax is not None and val \u003e= self.slidermax.val:\r\n            if not self.closedmax:\r\n                return\r\n            val = self.slidermax.val\r\n        return val\r\n\r\n    def _update(self, event):\r\n        \"\"\"Update the slider position.\"\"\"\r\n        if self.ignore(event) or event.button != 1:\r\n            return\r\n\r\n        if event.name == 'button_press_event' and event.inaxes == self.ax:\r\n            self.drag_active = True\r\n            event.canvas.grab_mouse(self.ax)\r\n\r\n        if not self.drag_active:\r\n            return\r\n\r\n        elif ((event.name == 'button_release_event') or\r\n              (event.name == 'button_press_event' and\r\n               event.inaxes != self.ax)):\r\n            self.drag_active = False\r\n            event.canvas.release_mouse(self.ax)\r\n            self.dot.set_markeredgecolor('grey')\r\n            self.dot.set_markerfacecolor('grey')\r\n            self.ax.figure.canvas.draw_idle()\r\n            return\r\n\r\n        if event.name == 'button_press_event':\r\n            self.dot.set_markeredgecolor('C0')\r\n            self.dot.set_markerfacecolor('C0')\r\n        if self.orientation == 'vertical':\r\n            val = self._value_in_bounds(event.ydata)\r\n        else:\r\n            val = self._value_in_bounds(event.xdata)\r\n        if val not in [None, self.val]:\r\n            self.set_val(val)\r\n    def set_val(self, val):\r\n        \"\"\"\r\n        Set slider value to *val*.\r\n        Parameters\r\n        ----------\r\n        val : float\r\n        \"\"\"\r\n        self.dot.set_xdata([val])\r\n        self.rect.set_width(val)\r\n        self.above_rect.set_x(val)\r\n        self.valtext.set_text(self._format(val))\r\n        if self.drawon:\r\n            self.ax.figure.canvas.draw_idle()\r\n        self.val = val\r\n        if self.eventson:\r\n            self._observers.process('changed', val)\r\n    def on_changed(self, func):\r\n        \"\"\"\r\n        Connect *func* as callback function to changes of the slider value.\r\n        Parameters\r\n        ----------\r\n        func : callable\r\n            Function to call when slider is changed.\r\n            The function must accept a single float as its arguments.\r\n        Returns\r\n        -------\r\n        int\r\n            Connection id (which can be used to disconnect *func*).\r\n        \"\"\"\r\n        return self._observers.connect('changed', lambda val: func(val))\r\n\r\ndef connnect_slider_to_ax(slider, ax):\r\n    t = np.arange(0.0, 1.0, 0.001)\r\n    f0 = 3\r\n    delta_f = 5.0\r\n    amp = 5\r\n    s = amp * np.sin(2 * np.pi * f0 * t)\r\n    l, = ax.plot(t, s, lw=2)\r\n    def update(val):\r\n        freq = slider.val\r\n        l.set_ydata(amp*np.sin(2*np.pi*freq*t))\r\n        # ax.figure.canvas.draw_idle()\r\n    slider.on_changed(update)\r\n\r\nif __name__ == '__main__':\r\n    import matplotlib.pyplot as plt\r\n    from matplotlib.widgets import Slider\r\n    # new style\r\n    fig, ax = plt.subplots()\r\n    plt.subplots_adjust(bottom=0.25)\r\n    new_slider_ax = plt.axes([0.25, 0.1, 0.65, 0.03])\r\n    sNew = newSlider(new_slider_ax, 'Freq', 0.1, 30.0,valinit=5)\r\n    connnect_slider_to_ax(sNew, ax)\r\n\r\n    fig2, ax2 = plt.subplots()\r\n    plt.subplots_adjust(bottom=0.25)\r\n    old_slider_ax = plt.axes([0.25, 0.1, 0.65, 0.03])\r\n    sOld = Slider(old_slider_ax, 'Freq', 0.1, 30.0, valinit=5)\r\n    connnect_slider_to_ax(sOld, ax2)\r\n\r\n    plt.show()\r\n```\r\n\u003c/p\u003e\u003c/details\u003e\r\n\r\nThe above script will generate these two figures for comparison. On the left is my new proposed style, and on the right is the current style:\r\n![comparing-sliders](https://user-images.githubusercontent.com/10111092/103973574-ab13f980-513d-11eb-9556-397fafd2b9a9.gif)\r\n\r\n\r\n\r\n### Additional context and prior art\r\n\r\nhttps://www.smashingmagazine.com/2017/07/designing-perfect-slider/\r\nhttps://material-ui.com/components/slider/\r\nhttps://ipywidgets.readthedocs.io/en/stable/examples/Widget%20List.html#IntSlider\r\n\u003c!-- Add any other context or screenshots about the feature request here. You can also include links to examples of other programs that have something similar to your request. For example:\r\n\r\n* Another project [...] solved this by [...]\r\n--\u003e","author":{"url":"https://github.com/ianhi","@type":"Person","name":"ianhi"},"datePublished":"2021-01-08T04:12:54.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/19256/matplotlib/issues/19256"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:f68feb43-683e-ad7e-3bbc-07b1bbe1f01f
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-id99C6:95C7C:1D0129F:27BE074:6A5485E4
html-safe-nonceca2c839b4277ab51c763f3f8d7abfc3ce4c088f3f688490f8d88efd29d3c64e7
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5OUM2Ojk1QzdDOjFEMDEyOUY6MjdCRTA3NDo2QTU0ODVFNCIsInZpc2l0b3JfaWQiOiI4ODU5NzUzNjg5NTUzNjQ4MzYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmac2e45070e3ea82ae7f897c1640c27690be79454de8a75cf1108bfd10dac4965c4
hovercard-subject-tagissue:781828969
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/matplotlib/matplotlib/19256/issue_layout
twitter:imagehttps://opengraph.githubassets.com/88f9b7f0a3ec7bc8e6c0e3da156c5c649805057d65424fdeffd71a0e1aaa9f34/matplotlib/matplotlib/issues/19256
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/88f9b7f0a3ec7bc8e6c0e3da156c5c649805057d65424fdeffd71a0e1aaa9f34/matplotlib/matplotlib/issues/19256
og:image:altProblem I've never loved the way Matplotlib Slider widgets look (and per jupyter-widgets/ipywidgets#3025 (comment) I am apparently not alone). However, beyond that I think that the current way the ...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernameianhi
hostnamegithub.com
expected-hostnamegithub.com
Noneb9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb
turbo-cache-controlno-preview
go-importgithub.com/matplotlib/matplotlib git https://github.com/matplotlib/matplotlib.git
octolytics-dimension-user_id215947
octolytics-dimension-user_loginmatplotlib
octolytics-dimension-repository_id1385122
octolytics-dimension-repository_nwomatplotlib/matplotlib
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id1385122
octolytics-dimension-repository_network_root_nwomatplotlib/matplotlib
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release03ccb116376fd46e8ba2a4cdc541e35f13f70734
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/matplotlib/matplotlib/issues/19256#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmatplotlib%2Fmatplotlib%2Fissues%2F19256
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmatplotlib%2Fmatplotlib%2Fissues%2F19256
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=matplotlib%2Fmatplotlib
Reloadhttps://github.com/matplotlib/matplotlib/issues/19256
Reloadhttps://github.com/matplotlib/matplotlib/issues/19256
Reloadhttps://github.com/matplotlib/matplotlib/issues/19256
Please reload this pagehttps://github.com/matplotlib/matplotlib/issues/19256
matplotlib https://github.com/matplotlib
matplotlibhttps://github.com/matplotlib/matplotlib
Please reload this pagehttps://github.com/matplotlib/matplotlib/issues/19256
Notifications https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Fork 8.4k https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Star 23k https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Code https://github.com/matplotlib/matplotlib
Issues 1.1k https://github.com/matplotlib/matplotlib/issues
Pull requests 408 https://github.com/matplotlib/matplotlib/pulls
Actions https://github.com/matplotlib/matplotlib/actions
Projects https://github.com/matplotlib/matplotlib/projects
Wiki https://github.com/matplotlib/matplotlib/wiki
Security and quality 0 https://github.com/matplotlib/matplotlib/security
Insights https://github.com/matplotlib/matplotlib/pulse
Code https://github.com/matplotlib/matplotlib
Issues https://github.com/matplotlib/matplotlib/issues
Pull requests https://github.com/matplotlib/matplotlib/pulls
Actions https://github.com/matplotlib/matplotlib/actions
Projects https://github.com/matplotlib/matplotlib/projects
Wiki https://github.com/matplotlib/matplotlib/wiki
Security and quality https://github.com/matplotlib/matplotlib/security
Insights https://github.com/matplotlib/matplotlib/pulse
#19265https://github.com/matplotlib/matplotlib/pull/19265
New Styling for Slidershttps://github.com/matplotlib/matplotlib/issues/19256#top
#19265https://github.com/matplotlib/matplotlib/pull/19265
New featurehttps://github.com/matplotlib/matplotlib/issues?q=state%3Aopen%20label%3A%22New%20feature%22
topic: widgets/UIhttps://github.com/matplotlib/matplotlib/issues?q=state%3Aopen%20label%3A%22topic%3A%20widgets%2FUI%22
v3.5.0https://github.com/matplotlib/matplotlib/milestone/59
https://github.com/ianhi
ianhihttps://github.com/ianhi
on Jan 8, 2021https://github.com/matplotlib/matplotlib/issues/19256#issue-781828969
jupyter-widgets/ipywidgets#3025 (comment)https://github.com/jupyter-widgets/ipywidgets/issues/3025#issuecomment-756263435
https://user-images.githubusercontent.com/10111092/103973574-ab13f980-513d-11eb-9556-397fafd2b9a9.gif
https://www.smashingmagazine.com/2017/07/designing-perfect-slider/https://www.smashingmagazine.com/2017/07/designing-perfect-slider/
https://material-ui.com/components/slider/https://material-ui.com/components/slider/
https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20List.html#IntSliderhttps://ipywidgets.readthedocs.io/en/stable/examples/Widget%20List.html#IntSlider
New featurehttps://github.com/matplotlib/matplotlib/issues?q=state%3Aopen%20label%3A%22New%20feature%22
topic: widgets/UIhttps://github.com/matplotlib/matplotlib/issues?q=state%3Aopen%20label%3A%22topic%3A%20widgets%2FUI%22
v3.5.0https://github.com/matplotlib/matplotlib/milestone/59
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.