master #3
@ -1,7 +1,47 @@
|
|||||||
body{
|
body{
|
||||||
|
position: relative;
|
||||||
|
margin:1em;
|
||||||
|
padding:0;
|
||||||
|
font-size: 120%;
|
||||||
|
line-height: 1.4;
|
||||||
color:purple;
|
color:purple;
|
||||||
|
background-color:#ff4d4d33;
|
||||||
|
}
|
||||||
|
hr{
|
||||||
|
border:0;
|
||||||
|
border-bottom:1px dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1{
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- slider --- */
|
||||||
|
|
||||||
|
|
||||||
|
div#sliders{
|
||||||
|
position: fixed;
|
||||||
|
width: 1000px;
|
||||||
|
height: 500px;
|
||||||
|
top:60px;
|
||||||
|
left:340px;
|
||||||
}
|
}
|
||||||
div#slider{
|
div#slider{
|
||||||
float: left;
|
float: left;
|
||||||
margin:0.5em 1em 1em 0.5em;
|
margin:0.5em 1em 1em 0.5em;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- control points ---*/
|
||||||
|
|
||||||
|
div.controlpoint{
|
||||||
|
max-width: 800px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rotterdam{
|
||||||
|
color:#0054ff;
|
||||||
|
}
|
||||||
|
#rotterdam li{
|
||||||
|
list-style: none;
|
||||||
}
|
}
|
108
index.html
108
index.html
@ -3,24 +3,46 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
|
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
|
||||||
<script type="text/javascript" src="js/Pathslider/js/jquery.pathslider.js"></script>
|
<script type="text/javascript" src="js/jquery.pathslider.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="css/stylesheet.css">
|
<link rel="stylesheet" type="text/css" href="css/stylesheet.css">
|
||||||
<link rel="stylesheet" type="text/css" href="css/pathslider.css">
|
<link rel="stylesheet" type="text/css" href="css/pathslider.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- The curved slider -->
|
<!-- The curved slider -->
|
||||||
|
<div id="sliders">
|
||||||
<div id="slider"></div>
|
<div id="slider"></div>
|
||||||
|
<div id="slider2"></div>
|
||||||
|
</div>
|
||||||
<style>
|
<style>
|
||||||
#slider {
|
#slider {
|
||||||
background : #eee url();
|
position: absolute;
|
||||||
width : 241px;
|
top:0;
|
||||||
height : 266px;
|
left:0;
|
||||||
|
width : 100%;
|
||||||
|
height : 400px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
#slider2 {
|
||||||
|
position: absolute;
|
||||||
|
top:0;
|
||||||
|
left:0;
|
||||||
|
width : 100%;
|
||||||
|
height : 400px;
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
jQuery(function($){
|
jQuery(function($){
|
||||||
$("#slider").pathslider({
|
$("#slider").pathslider({
|
||||||
points : [50,10,-150,0,150,300,200,50],
|
points : [50,10,-150,0,150,200,300,100],
|
||||||
|
value : 49,
|
||||||
|
rotateGrip : true,
|
||||||
|
tolerance : 3,
|
||||||
|
range : 30,
|
||||||
|
curve : { width:4, color:"#333", cap:"round" }
|
||||||
|
});
|
||||||
|
$("#slider2").pathslider({
|
||||||
|
points : [490,300,-150,0,-200,-200,300,100],
|
||||||
value : 49,
|
value : 49,
|
||||||
rotateGrip : true,
|
rotateGrip : true,
|
||||||
tolerance : 3,
|
tolerance : 3,
|
||||||
@ -31,8 +53,82 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="curve">
|
<div id="curve">
|
||||||
<h1>Relearn curved</h1>
|
<h1>Relearn
|
||||||
|
<select onchange="window.location.href=this.value" style="display: inline-block;">
|
||||||
|
<option value="http://relearn.be/2019/" selected="selected">2019</option>
|
||||||
|
<option value="http://relearn.be/2017/">2017</option>
|
||||||
|
<option value="http://relearn.be/2016/">2016</option>
|
||||||
|
<option value="http://relearn.be/2015/">2015</option>
|
||||||
|
<option value="http://relearn.be/2014/">2014</option>
|
||||||
|
<option value="http://relearn.be/2013/">2013</option>
|
||||||
|
</select>
|
||||||
|
curved</h1>
|
||||||
|
|
||||||
|
<p>Relearn 2019 is a curve, transversing multiple times and spaces.</p>
|
||||||
|
|
||||||
|
<div id="rotterdam" class="controlpoint">
|
||||||
|
<h2>RELEARN 2019.Rotterdam</h2>
|
||||||
|
|
||||||
|
<p>7th, 8th & 9th of June 2019<br>
|
||||||
|
Varia, Rotterdam</p><br>
|
||||||
|
|
||||||
|
<p>For the Rotterdam control point on the curve, we propose to together attend to a <strong>subject zone</strong> (<strong>*</strong>) where different digital network practices intersect. This subject zone can morph into multiple directions throughout the session. Our specific interest is in how <strong>publishing formats</strong> (<strong>**</strong>) operate with/on/through this energy field.</p>
|
||||||
|
<p><strong>*</strong> There are many questions in the air when we start to speak about digital infrastructures, hosters, servers, services, networks and their attachments to all these technical realities. Instead of picking one and diving deeper, we thought it would be more interesting to present a range and explore different vocabularies, protocols, technologies, infrastructures. We invite you to join Relearn to stretch this zone, starting from or moving towards:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>▝ digital interdependencies</li>
|
||||||
|
<li>▘ affective infrastructures</li>
|
||||||
|
<li>▗ networked entanglements</li>
|
||||||
|
<li>▖ feminist servers</li>
|
||||||
|
<li>▖ federated networks</li>
|
||||||
|
<li>▝ and-and-networks</li>
|
||||||
|
<li>▚ digital autonomy</li>
|
||||||
|
<li>▝ homebrewed networks</li>
|
||||||
|
<li>▖ transitional infrastructures</li>
|
||||||
|
<li>▞ digital selves-organisation</li>
|
||||||
|
<li>▖ so-and-sovereignty networks</li>
|
||||||
|
<li>▝ out-of-the-cloud thinking</li>
|
||||||
|
<li>▚ …</li>
|
||||||
|
</ul>
|
||||||
|
<p><strong>**</strong> We’re curious about learning trajectories that connect to a subject through publishing formats. The different publishing formats serve as an invitation to embed ourselves within the subject zone of digital networks. How can these formats be our morphable lenses, that we use to relearn digital networks? Starting from or moving towards:</p>
|
||||||
|
<ul>
|
||||||
|
<li>▝ multiple readers</li>
|
||||||
|
<li>▖ cross-readings created through algorithms</li>
|
||||||
|
<li>▞ logbooks</li>
|
||||||
|
<li>▝ syllabi</li>
|
||||||
|
<li>▚ documentation</li>
|
||||||
|
<li>▖ annotations</li>
|
||||||
|
<li>▝ cookbooks</li>
|
||||||
|
<li>▖ tutorials</li>
|
||||||
|
<li>▚ README</li>
|
||||||
|
<li>▖ bug reports</li>
|
||||||
|
<li>▗ link dumps</li>
|
||||||
|
<li>▝ scores</li>
|
||||||
|
<li>▖ …</li>
|
||||||
|
</ul>
|
||||||
|
<p>Many sub-trajectories can emerge from here during the days, without the need of taking the same path or agreeing about vocabularies or geometries altogether.</p>
|
||||||
|
<hr />
|
||||||
|
<p>The session will take place in Rotterdam and starts on Friday evening (the 7th) in a public setting, followed by two full days of relearning together.</p>
|
||||||
|
<p><strong>Friday 7th June 20:00 - 22:00</strong><br>
|
||||||
|
Relearn public evening program: embed yourself into Relearn</p>
|
||||||
|
<p><strong>Satuday/Sunday 8-9th June 10:00 - 18:00</strong><br>
|
||||||
|
Relearn sub-zone-trajectories</p>
|
||||||
|
<p>If you would like to join this Relearn session, please send an email to <a href="mailto:info@varia.zone">info@varia.zone</a> with a short motivation of your interest. We will reply to subscriptions on a regular basis, up to the <strong>26th of May</strong>.</p>
|
||||||
|
<p>Our <em>capacities</em> allow us to have a group of 30 relearners. Our preference goes out to people that can join the whole session (Friday evening, Saturday and Sunday). We will take care of a <em>daily vegetarian lunch</em> (please let us know about allergies or other dietary preferences). Following a tradition from previous years, we will arrange a <em>hosting network</em> in the city and find a place to stay for everyone. If you live in Rotterdam (or in the Netherlands) please mention in the email if you need to be hosted or could host one or more relearners in your house.</p>
|
||||||
|
<p>If you would like to join us only on the Friday evening, there is no need to subscribe, just come over! :)</p>
|
||||||
|
<hr />
|
||||||
|
<p><u>Practical info</u><br>
|
||||||
|
Date: 7th-9th June 2019 <br>
|
||||||
|
Location: Varia - Gouwstraat 3, Rotterdam, The Netherlands<br>
|
||||||
|
Website: <a href="https://varia.zone/en/" class="uri">https://varia.zone/</a></p>
|
||||||
|
<p><u>Resources & contact</u><br>
|
||||||
|
→ email: <a href="mailto:info@varia.zone"> info@varia.zone</a><br>
|
||||||
|
→ <a href="https://tumulte.domainepublic.net/cgi-bin/mailman/listinfo/relearn" class="uri">subscribe to the Relearn mailinglist </a><br>
|
||||||
|
→ <a href="https://gitlab.com/relearn" class="uri">Relearn’s gitlab repository </a><br>
|
||||||
|
→ <a href="https://webchat.freenode.net/" class="uri">IRC channel: #relearn on Freenode</a><br>
|
||||||
|
→ <a href="https://gallery.constantvzw.org/index.php/search?album=1&q=relearn" class="uri">Photographs of previous Relearn editions can be found in Constant’s gallery</a></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
Subproject commit 633a5cba0a5149fa3085dff2cb0a8e7e324b1215
|
|
402
js/jquery.pathslider.js
Normal file
402
js/jquery.pathslider.js
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
/* jQuery Pathslider v1.0.0 alpha
|
||||||
|
* By Rob Garrison (Mottie)
|
||||||
|
* MIT License
|
||||||
|
*/
|
||||||
|
(function($){
|
||||||
|
$.pathslider = function(el, options){
|
||||||
|
|
||||||
|
// To avoid scope issues, use 'base' instead of 'this'
|
||||||
|
// to reference this class from internal events and functions.
|
||||||
|
var base = this, o;
|
||||||
|
|
||||||
|
// Access to jQuery and DOM versions of element
|
||||||
|
base.$el = $(el).addClass('pathslider');
|
||||||
|
base.el = el;
|
||||||
|
|
||||||
|
// Add a reverse reference to the DOM object
|
||||||
|
base.$el.data("pathslider", base);
|
||||||
|
|
||||||
|
base.init = function(){
|
||||||
|
var t;
|
||||||
|
base.options = o = $.extend(true, {}, $.pathslider.defaults, options);
|
||||||
|
|
||||||
|
// Is there a canvas?
|
||||||
|
t = document.createElement('canvas');
|
||||||
|
base.hasCanvas = !!(t.getContext && t.getContext('2d'));
|
||||||
|
base.hasTouch = document.hasOwnProperty("ontouchend");
|
||||||
|
|
||||||
|
// add grip
|
||||||
|
base.$grip = $('<div></div>').appendTo(base.$el);
|
||||||
|
|
||||||
|
// store array of x & y positions for cross reference
|
||||||
|
base.points = [];
|
||||||
|
base.pointsxy = [];
|
||||||
|
base.arrayX = [];
|
||||||
|
base.arrayY = [];
|
||||||
|
base.arrayP = [];
|
||||||
|
|
||||||
|
base.rad2deg = 180 / Math.PI; // convert radians to degrees (multiply radian by this value)
|
||||||
|
base.sliding = false; // flag for dragging element
|
||||||
|
base.lastPercent = base.percent = o.value;
|
||||||
|
|
||||||
|
// Callbacks
|
||||||
|
// slide triggered on EVERY mouse move; change triggered on slide stop
|
||||||
|
$.each('create update start slide change stop'.split(' '), function(i,f){
|
||||||
|
if ($.isFunction(o[f])){
|
||||||
|
base.$el.bind(f + '.pathslider', o[f]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.bind( base.hasTouch ? 'touchend.pathslider touchcancel.pathslider' : 'mouseup.pathslider mouseleave.pathslider', function(e){
|
||||||
|
if (base.sliding) { // && ($(e.target).closest('.pathslider').length || e.type === 'mouseleave')) {
|
||||||
|
base.$el.trigger('stop.pathslider', [base]);
|
||||||
|
if (base.lastPercent !== base.percent) {
|
||||||
|
base.lastPercent = base.percent;
|
||||||
|
base.$el.trigger('change.pathslider', [base]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.$grip.removeClass('sliding');
|
||||||
|
base.sliding = false;
|
||||||
|
})
|
||||||
|
.bind( (base.hasTouch ? 'touchmove' : 'mousemove') + '.pathslider', function(e){
|
||||||
|
if (base.sliding) {
|
||||||
|
base.setSlider( base.findPos(e), null, true );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(window)
|
||||||
|
.bind('resize.pathslider', function(){
|
||||||
|
base.update();
|
||||||
|
})
|
||||||
|
.bind('load', function(){
|
||||||
|
// needed because loading images/fonts will shift the page
|
||||||
|
base.sliderDim[0] = base.$el.offset().left;
|
||||||
|
base.sliderDim[1] = base.$el.offset().top;
|
||||||
|
});
|
||||||
|
|
||||||
|
base.$grip
|
||||||
|
.bind( (base.hasTouch ? 'touchstart' : 'mousedown') + '.pathslider', function(e){
|
||||||
|
base.sliding = true;
|
||||||
|
$(this).addClass('sliding');
|
||||||
|
base.$el.trigger('start.pathslider', [base]);
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.bind('click', function(){
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
base.redraw();
|
||||||
|
|
||||||
|
base.$el.trigger('create.pathslider', [base]);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// update dimensions & grip position
|
||||||
|
base.update = function(){
|
||||||
|
|
||||||
|
// using attr to remove other css grip classes when updating
|
||||||
|
base.$grip.attr('class', 'pathslider-grip ' + o.gripClass);
|
||||||
|
|
||||||
|
if (base.ctx) {
|
||||||
|
// clear canvas *before* setting new dimensions
|
||||||
|
// just in case the new size is smaller than the previous
|
||||||
|
base.ctx.clearRect(0, 0, base.sliderDim[2], base.sliderDim[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.sliderDim = [
|
||||||
|
base.$el.offset().left,
|
||||||
|
base.$el.offset().top,
|
||||||
|
base.$el.width(),
|
||||||
|
base.$el.height()
|
||||||
|
];
|
||||||
|
|
||||||
|
// get grip dimensions; jQuery v3+ width() & height() return the rotated dimensions
|
||||||
|
// which we don't want!
|
||||||
|
var computedStyle = window.getComputedStyle(base.$grip[0]);
|
||||||
|
// for centering grip
|
||||||
|
base.gripCenter = [ parseInt(computedStyle.width, 10)/2, parseInt(computedStyle.height, 10)/2 ];
|
||||||
|
|
||||||
|
// number of data points to store - increase to smooth the animation (based on slider size)
|
||||||
|
base.dataPoints = o.dataPoints;
|
||||||
|
// in next update add min/max/step
|
||||||
|
// base.range = o.max - o.min;
|
||||||
|
// base.dataPoints = base.range * o.step;
|
||||||
|
|
||||||
|
base.makeArray();
|
||||||
|
// save the position in the array of the starting value (roughly)
|
||||||
|
var t = $.inArray(base.percent, base.arrayP);
|
||||||
|
base.position = (t === -1) ? Math.round(base.percent/100 * base.dataPoints) : t;
|
||||||
|
|
||||||
|
base.setSlider(base.percent, null, true);
|
||||||
|
if (base.hasCanvas && o.useCanvas) { base.drawCurve(); }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// set position of slider
|
||||||
|
base.setSlider = function(percent, callback, internal) {
|
||||||
|
if (!isNaN(percent)) {
|
||||||
|
// find position on bezier curve; p = percent (range 0 - 100)
|
||||||
|
// set position of slider without using the array (more precision)
|
||||||
|
percent = parseFloat(percent, 10);
|
||||||
|
percent = (percent > 100) ? 100 : percent < 0 ? 0 : percent;
|
||||||
|
var css, angle,
|
||||||
|
// pos = $.inArray(percent, base.arrayP),
|
||||||
|
p = base.calcBezier(percent/100, base.pointsxy),
|
||||||
|
pm1 = (percent - 2 > 0) ? base.calcBezier( (percent-2)/100, base.pointsxy ) : p,
|
||||||
|
pp1 = (percent + 2 < 100) ? base.calcBezier( (percent+2)/100, base.pointsxy ) : p,
|
||||||
|
// m = slope of tangent - used to change rotation angle of the grip
|
||||||
|
// yes, I could have used the cubic derivative, but this is less math
|
||||||
|
m = (pp1[0] - pm1[0] === 0) ? 90 : (pp1[1] - pm1[1])/(pp1[0] - pm1[0]);
|
||||||
|
base.angle = parseInt(Math.atan(m) * base.rad2deg, 10);
|
||||||
|
angle = 'rotate(' + base.angle + 'deg)';
|
||||||
|
css = (o.rotateGrip) ? {
|
||||||
|
'-webkit-transform' : angle,
|
||||||
|
'transform' : angle
|
||||||
|
} : {};
|
||||||
|
css.left = p[0] - base.gripCenter[0];
|
||||||
|
css.top = p[1] - base.gripCenter[1];
|
||||||
|
base.$grip
|
||||||
|
.attr({
|
||||||
|
'data-angle' : base.angle,
|
||||||
|
'data-percent' : percent
|
||||||
|
})
|
||||||
|
.css(css);
|
||||||
|
// find closest percent in the array - this relies on there being a factor
|
||||||
|
// of 100 datapoints, so it'll need changing when we have a min/max/step
|
||||||
|
base.percent = percent; // Math.round(percent*r)/r;
|
||||||
|
if ((percent !== base.lastPercent && !base.sliding) || !internal) {
|
||||||
|
base.$el.trigger('change.pathslider', [base]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof callback === 'function') { callback(base); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// relative mouse position
|
||||||
|
base.mousePos = function(e) {
|
||||||
|
return [
|
||||||
|
(e.originalEvent.touches ? e.originalEvent.touches[0].pageX : e.pageX) - base.sliderDim[0],
|
||||||
|
(e.originalEvent.touches ? e.originalEvent.touches[0].pageY : e.pageY) - base.sliderDim[1]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
// find percentage given the x,y coordinates
|
||||||
|
// searching through a set array of points starting from the last known position
|
||||||
|
// This allows the curve to loop over itself without mixing up intersecting points
|
||||||
|
// The biggest issue is a very sharp turn
|
||||||
|
base.findPos = function(event) {
|
||||||
|
var i, j, dx, dy, px = [], py = [],
|
||||||
|
last = base.position, //* base.dataPoints / 100,
|
||||||
|
// check x & y cross ref based on nearby positions (+/- tolerance)
|
||||||
|
t = parseInt(o.tolerance + 1, 10) || 2, // tolerance of 1 is too small
|
||||||
|
r = parseInt(o.range, 10) || base.gripCenter[0], // set to 1/2 width of grip
|
||||||
|
pos = base.mousePos(event);
|
||||||
|
// save percent
|
||||||
|
for ( i=0; i < r; i++ ){
|
||||||
|
px = []; py = [];
|
||||||
|
for ( j=0; j < t + 1; j++ ){
|
||||||
|
// check positive direction
|
||||||
|
dx = Math.abs(base.arrayX[last+j] - pos[0]) <= i;
|
||||||
|
dy = Math.abs(base.arrayY[last+j] - pos[1]) <= i;
|
||||||
|
if (dx && dy) { return base.returnPos(last+j); }
|
||||||
|
if (dx) { px.push(last+j); }
|
||||||
|
if (dy) { py.push(last+j); }
|
||||||
|
// check in negative direction
|
||||||
|
dx = Math.abs(base.arrayX[last-j] - pos[0]) <= i;
|
||||||
|
dy = Math.abs(base.arrayY[last-j] - pos[1]) <= i;
|
||||||
|
if (dx && dy) { return base.returnPos(last-j); }
|
||||||
|
if (dx) { px.push(last-j); }
|
||||||
|
if (dy) { py.push(last-j); }
|
||||||
|
}
|
||||||
|
if (px.length === 1 && py.length > 1) { return base.returnPos(px[0]); }
|
||||||
|
if (py.length === 1 && px.length > 1) { return base.returnPos(py[0]); }
|
||||||
|
}
|
||||||
|
return base.returnPos(last);
|
||||||
|
};
|
||||||
|
|
||||||
|
// return found position & trigger slide event
|
||||||
|
base.returnPos = function(p) {
|
||||||
|
var t = base.position === p;
|
||||||
|
base.percent = base.arrayP[p];
|
||||||
|
base.position = p;
|
||||||
|
if (!t) {
|
||||||
|
if (base.hasCanvas && o.useCanvas) {
|
||||||
|
base.drawCurve();
|
||||||
|
}
|
||||||
|
base.$el.trigger('slide.pathslider', [base] );
|
||||||
|
}
|
||||||
|
return base.percent;
|
||||||
|
};
|
||||||
|
|
||||||
|
// build cross-ref array - find position based on x,y coords
|
||||||
|
base.makeArray = function(){
|
||||||
|
var i, t, b = base.pointsxy,
|
||||||
|
n = base.dataPoints;
|
||||||
|
for ( i=0; i < n+1; i++ ){
|
||||||
|
t = base.calcBezier(i/n, b);
|
||||||
|
base.arrayX[i] = t[0];
|
||||||
|
base.arrayY[i] = t[1];
|
||||||
|
base.arrayP[i] = t[2];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate bezier x & y based on percentage (p)
|
||||||
|
// cubic bezier = start(p^3) + cstart(3*p^2*(1−p)) + cend(3*p*(1−p)^2) + end(1−p)^3
|
||||||
|
// b = [ startx,starty, cstartx,cstarty, cendx,cendy, endx,endy ]
|
||||||
|
base.calcBezier = function(p,b){
|
||||||
|
var p2 = p*p,
|
||||||
|
omp = (1-p), // omp = one minus p - smart naming ftw!
|
||||||
|
omp2 = omp*omp,
|
||||||
|
f1 = omp*omp2,
|
||||||
|
f2 = 3*p*omp2,
|
||||||
|
f3 = 3*p2*omp,
|
||||||
|
f4 = p*p2;
|
||||||
|
return [
|
||||||
|
Math.round(b[0]*f1 + b[2]*f2 + b[4]*f3 + b[6]*f4), // bezier x
|
||||||
|
Math.round(b[1]*f1 + b[3]*f2 + b[5]*f3 + b[7]*f4), // bezier y
|
||||||
|
Math.round(p*1000)/10 // percentage with one decimal place
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
// base.points = [ sx,sy, csxo,csyo, cexo,ceyo, ex,ey ]
|
||||||
|
// sx,sy = start x & y
|
||||||
|
// csxo,csyo = control start x & y offset from start point
|
||||||
|
// cexo,ceyo = control end x & y offset from end point
|
||||||
|
// ex,ey = end x & y
|
||||||
|
// convert needed for canvas - using the offset just makes the code easier to read
|
||||||
|
// base.pointsxy = [ sx, sy, csx, csy, cex, cey, ex, ey ]
|
||||||
|
base.convert2xy = function(p){
|
||||||
|
p = p || base.points;
|
||||||
|
return [
|
||||||
|
p[0], p[1], // start x,y
|
||||||
|
p[0] + p[2], p[1] + p[3], // start control x,y
|
||||||
|
p[6] + p[4], p[7] + p[5], // end control x,y
|
||||||
|
p[6], p[7] // end x,y
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
base.redraw = function(points) {
|
||||||
|
// update from options
|
||||||
|
base.points = base.options.points = points || base.options.points;
|
||||||
|
// store array of x & y positions for cross reference
|
||||||
|
base.pointsxy = base.convert2xy();
|
||||||
|
// update grip
|
||||||
|
base.update();
|
||||||
|
// update curve
|
||||||
|
base.drawCurve();
|
||||||
|
base.setSlider(base.percent, null, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make purdy curve
|
||||||
|
base.drawCurve = function() {
|
||||||
|
var ctx, grad, tmp,
|
||||||
|
points = base.pointsxy;
|
||||||
|
if (!base.$el.find('canvas').length) {
|
||||||
|
$('<canvas class="pathslider-canvas"></canvas>').appendTo(base.$el);
|
||||||
|
// size in attribute needed to keep canvas size in proportion
|
||||||
|
base.$canvas = base.$el.find('canvas').attr({ width: base.sliderDim[2], height: base.sliderDim[3] });
|
||||||
|
base.canvas = base.$canvas[0];
|
||||||
|
base.ctx = base.canvas.getContext("2d");
|
||||||
|
}
|
||||||
|
ctx = base.ctx;
|
||||||
|
ctx.clearRect(0, 0, base.sliderDim[2], base.sliderDim[3]);
|
||||||
|
ctx.lineCap = o.curve.cap;
|
||||||
|
ctx.lineJoin = o.curve.cap;
|
||||||
|
ctx.lineWidth = o.curve.width;
|
||||||
|
// this can be a gradient or image as well. See
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Applying_styles_and_colors
|
||||||
|
if ($.isArray(o.curve.color)) {
|
||||||
|
grad = ctx.createLinearGradient(points[0], points[1], points[6], points[7]);
|
||||||
|
tmp = base.percent/100;
|
||||||
|
grad.addColorStop(0, o.curve.color[0]);
|
||||||
|
grad.addColorStop(tmp, o.curve.color[0]);
|
||||||
|
if (tmp + 0.01 <= 1) { tmp += 0.01; }
|
||||||
|
grad.addColorStop(tmp, o.curve.color[1]);
|
||||||
|
grad.addColorStop(1, o.curve.color[1]);
|
||||||
|
ctx.strokeStyle = grad;
|
||||||
|
} else {
|
||||||
|
ctx.strokeStyle = o.curve.color;
|
||||||
|
}
|
||||||
|
tmp = true;
|
||||||
|
if (typeof o.drawCanvas === 'function') {
|
||||||
|
// return anything except false to continue drawing the curve
|
||||||
|
tmp = o.drawCanvas(base, ctx, points) !== false;
|
||||||
|
ctx = base.ctx;
|
||||||
|
}
|
||||||
|
// tmp returned from drawCanvas; if
|
||||||
|
if (tmp === true) {
|
||||||
|
base.finishCurve(ctx, points);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
base.finishCurve = function(ctx, points) {
|
||||||
|
ctx = ctx || base.ctx;
|
||||||
|
points = points || base.pointsxy;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(points[0], points[1]);
|
||||||
|
ctx.bezierCurveTo(points[2], points[3], points[4], points[5], points[6], points[7]);
|
||||||
|
ctx.stroke();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run initializer
|
||||||
|
base.init();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pathslider.defaults = {
|
||||||
|
|
||||||
|
// Appearance
|
||||||
|
gripClass : '', // class added to the grip/handle
|
||||||
|
rotateGrip : true, // when true, the grip will rotate based on the shape of the path
|
||||||
|
|
||||||
|
// canvas curve styling
|
||||||
|
useCanvas : true,
|
||||||
|
curve : { width: 4, color: "#333", cap: "round" },
|
||||||
|
|
||||||
|
// Usability
|
||||||
|
// sx,sy = start x & y
|
||||||
|
// csxo,csyo = control start x & y offset from start point
|
||||||
|
// cexo,ceyo = control end x & y offset from end point
|
||||||
|
// ex,ey = end x & y
|
||||||
|
// [ sx,sy, csxo,csyo, cexo,ceyo, ex,ey ]
|
||||||
|
points : [ 0,50, 50,-50, -50,-50, 250,50 ],
|
||||||
|
|
||||||
|
value : 50, // starting value - range 0 - 100%
|
||||||
|
// min : 0, // minimum value on the slider
|
||||||
|
// max : 100, // maximum value on the slider
|
||||||
|
// step : 1, // step to use between min and max
|
||||||
|
|
||||||
|
// Tweaking
|
||||||
|
dataPoints: 100, // Total number of points of the curve to save; increase in increments of 100 to smooth out the grip movement, but not more than 500 (it slows everything down)
|
||||||
|
tolerance : 3, // distance on the curve from the last position to check; increase this to scroll faster
|
||||||
|
range : 30 // distance, in pixels, from the cursor to a matching x/y on the curve (should be about the same size as the grip)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.pathslider = function(options, callback){
|
||||||
|
return this.each(function(){
|
||||||
|
var percent, slider = $(this).data('pathslider');
|
||||||
|
|
||||||
|
// initialize the slider but prevent multiple initializations
|
||||||
|
if ((typeof(options)).match('object|undefined')){
|
||||||
|
if (!slider) {
|
||||||
|
(new $.pathslider(this, options));
|
||||||
|
} else {
|
||||||
|
return slider.redraw();
|
||||||
|
}
|
||||||
|
// If options is a number, set percentage
|
||||||
|
} else if (/\d/.test(options) && !isNaN(options) && slider) {
|
||||||
|
percent = (typeof(options) === "number") ? options : parseInt($.trim(options),10); // accepts " 2 "
|
||||||
|
// ignore out of bound percentages
|
||||||
|
if ( percent >= 0 && percent <= 100 ) {
|
||||||
|
slider.setSlider(percent, callback); // set percent & callback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.getpathslider = function(){
|
||||||
|
return this.data('pathslider');
|
||||||
|
};
|
||||||
|
|
||||||
|
})(jQuery);
|
Loading…
Reference in New Issue
Block a user