This shows the technique for a common 'pull to refresh' component drawn with Illustrator with the help of Impetus to handle momentum and rubber-band.
Test with your mobile device by clicking here
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <link rel="stylesheet" type="text/css" href="lib.css" /> | |
| <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
| <script src="//cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.6/fastclick.min.js"></script> | |
| <script src="http://chrisbateman.github.io/impetus/impetus.min.js"></script> | |
| <meta name="viewport" content='width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0' /> | |
| <meta name="apple-mobile-web-app-capable" content="yes" /> | |
| <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> | |
| <meta name="mobile-web-app-capable" content="yes" /> | |
| <meta name="apple-mobile-web-app-title" content="prototypon"> | |
| <meta name="application-name" content="prototypon"> | |
| <style type="text/css"> | |
| /* | |
| using font-face instead the js from google to override the default font name | |
| to adapt to the name given by Illustrator (i.e. AI use font-family:'Lato-Medium' instead font-family:'Lato':font-weight:300; */ | |
| @font-face { | |
| font-family: 'Lato-Bold'; | |
| font-style: normal; | |
| font-weight: 400; | |
| src: local('Lato Regular'), local('Lato-Regular'), url(https://fonts.gstatic.com/s/lato/v11/MDadn8DQ_3oT6kvnUq_2r_esZW2xOQ-xsNqO47m55DA.woff2) format('woff2'), url(https://fonts.gstatic.com/s/lato/v11/qIIYRU-oROkIk8vfvxw6QvesZW2xOQ-xsNqO47m55DA.woff) format('woff'); | |
| } | |
| </style> | |
| </head> | |
| <body class="mobileready"> | |
| <script> | |
| var svg_path = "ui.svg" // specify the svg filename/path | |
| function init(){ | |
| var content = d3.select('#drawer') | |
| var ya = d3.select('#ya') | |
| var mapOpacity = d3.scale.linear() | |
| .domain([0, 150]) | |
| .range([0, 1]) | |
| new Impetus({ | |
| source: content.node(), | |
| boundY: [-.5, 0], | |
| initialValues: [0, 0], | |
| update: function(x, y) { | |
| content.attr('transform', 'translate(0, '+y+')') | |
| ya.attr('transform', 'translate(0, '+y/2+')') | |
| .attr('opacity', mapOpacity(y)) | |
| } | |
| }); | |
| } | |
| </script> | |
| <script src="lib.js"></script> | |
| </body> | |
| </html> |
| * { | |
| box-sizing:border-box; | |
| } | |
| html{ | |
| width:100%; | |
| height:100%; | |
| } | |
| body{ | |
| width:100%; | |
| padding:0; | |
| margin:0; | |
| overflow: hidden; | |
| } | |
| body.mobileready{ | |
| height:100%; | |
| } | |
| svg{ | |
| width:100%; | |
| overflow: inherit; | |
| } | |
| body.mobileready svg{ | |
| height:100%; | |
| } | |
| svg *{ | |
| -webkit-tap-highlight-color: rgba(0,0,0,0); | |
| -webkit-touch-callout: none; | |
| -webkit-user-select: none; | |
| -khtml-user-select: none; | |
| -moz-user-select: none; | |
| -ms-user-select: none; | |
| user-select: none; | |
| } | |
| svg text{ | |
| pointer-events: none; | |
| } | |
| @media(max-device-width: 600px){ | |
| html, body.mobileready{ | |
| height:inherit; | |
| } | |
| /*body.mobileready svg{ | |
| height:inherit; | |
| }*/ | |
| } |
| d3.xml(svg_path, "image/svg+xml", function(xml) { | |
| d3.select('body').node().appendChild(xml.documentElement); | |
| // avoid this in iOS-7 | |
| d3.select('svg') | |
| .attr('width', null) | |
| .attr('height', null) | |
| FastClick.attach(document.body); | |
| init() | |
| }) | |
| /* | |
| Convenient function to clone an element in the same parent | |
| */ | |
| function clone(selector) { | |
| var node = d3.select(selector).node(); | |
| return d3.select(node.parentNode.insertBefore(node.cloneNode(true), node.nextSibling)); | |
| } | |
| /* | |
| Convenient function to set a clip-path to an element. | |
| The markup should follows this structure: | |
| <g id="{selector_component}"> | |
| <g id="{selector_content}">...</g> | |
| <g id="{selector_mask}">...</g> | |
| </g> | |
| */ | |
| function clip(selector_component, selector_mask, selector_content){ | |
| var component = d3.select(selector_component) | |
| var mask = d3.select(selector_mask).node() | |
| var content = d3.select(selector_content) | |
| component.append('defs') | |
| .node() | |
| .appendChild(mask) | |
| var clipname = 'maskclip' + selector_component.replace('#', '_') | |
| component.append('clipPath') | |
| .attr('id', clipname) | |
| .append('use') | |
| .attr('xlink:href', selector_mask) | |
| component.attr('clip-path', 'url(#'+clipname+')') | |
| } |