Skip to content

Instantly share code, notes, and snippets.

@McNull
Forked from anonymous/index.html
Created September 14, 2016 07:35
Show Gist options
  • Save McNull/ea3e87e7022fef2878e0c208e85b71a8 to your computer and use it in GitHub Desktop.
Save McNull/ea3e87e7022fef2878e0c208e85b71a8 to your computer and use it in GitHub Desktop.
SVG ring 4
<div class="container" ng-app="app">
<div ng-controller="MyCtrl as vm">
<svg width="400" viewbox="-300 -300 600 600">
<g id="circle" style="transform: rotate({{vm.circleRotate}}deg)" ng-class="{ dragging: vm.dragStart }">
<circle fill="#F1F1F1" cy="0" cx="0" ng-attr-r="{{ ::vm.circleRadius }}"></circle>
<g ng-repeat="icon in vm.icons" class="icon" ng-attr-transform="{{ 'rotate(-' + vm.iconRotate * $index + ') translate(0, ' + (vm.circleRadius - vm.iconSize) + ')' }}">
<rect ng-attr-width="{{ ::vm.iconSize }}"
ng-attr-height="{{ ::vm.iconSize }}"
ng-attr-fill="{{ icon.color }}"
ng-attr-x="{{ ::-(vm.iconSize/2) }}"
ng-attr-y="{{ ::-(vm.iconSize/2) }}"></rect>
<text ng-attr-x="0" ng-attr-y="5"
text-anchor="middle"
font-family="Verdana"
font-size="20">
{{ $index }}
</text>
</g>
</g>
</svg>
<button ng-click='vm.addIcon()'>Add</button>
<button ng-click='vm.removeIcon()'>Remove</button>
<input type="number" ng-model="vm.activeIndex"/>
</div>
</div>
var app = angular.module('app', []);
class MyCtrl {
constructor($scope, $element, $timeout) {
this.circleRotate = 0;
this.circleRadius = 300;
this.icons = [];
this.iconSize = 60;
this.activeIndex = 0;
this.dragDir = 0; // dragDir should actually be dragAngle
this.scope = $scope;
this.timeout = $timeout;
var iconCount = 9;
for(var i = 0; i < iconCount; i++) {
this.addIcon();
}
$scope.$watch(() => this.icons.length, () => {
this.iconRotate = 360/this.icons.length;
});
$scope.$watchGroup([
() => this.iconRotate,
() => this.activeIndex,
() => this.dragDir
], () => {
// console.log(this.activeIndex, this.iconRotate, this.dragDir);
this.circleRotate = this.activeIndex * this.iconRotate + this.dragDir;
});
this.registerDrag($element[0]);
}
registerDrag(container) {
var self = this;
function mousedown(e) {
document.body.addEventListener('mousemove', mousemove);
document.body.addEventListener('mouseup', mouseup);
self.dragStart = {
x: e.x, y: e.y
};
}
function mousemove(e) {
self.scope.$apply(() => {
// need to get the origin of the rotation
// http://stackoverflow.com/questions/10298658/mouse-position-inside-autoscaled-svg
var x = Math.atan2(e.x - self.dragStart.x, e.y - self.dragStart.y);
x = x * (180 / Math.PI);
console.log('x', x);
self.dragDir = self.dragStart.x - e.x;
// console.log('dragDir', self.dragDir);
});
}
function mouseup(e) {
document.body.removeEventListener('mousemove', mousemove);
document.body.removeEventListener('mouseup', mouseup);
self.scope.$apply(() => {
// set circle rot 0-360 range
self.circleRotate = (self.circleRotate + 360) % 360;
// if circle rot was negative we want to avoid a 360 deg spinning
// let the css adjust (without transition duration set)
self.timeout(() => {
delete self.dragStart;
self.dragDir = 0;
// map active index (rot/iconRotate)
self.activeIndex = Math.round(self.circleRotate / self.iconRotate);
// console.log(self.activeIndex);
});
});
}
container.addEventListener('mousedown', mousedown);
}
addIcon() {
var iconColor = '#EB6A05';
this.icons.push({
color: iconColor
});
}
removeIcon() {
this.icons.length -= 1;
}
}
app.controller('MyCtrl', MyCtrl);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
.container {
padding: 20px;
margin-left: auto;
margin-right: auto;
width: 300px;
}
svg {
border: 1px solid black;
}
svg text {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#circle {
transition: all 1s;
}
#circle.dragging {
transition: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment