Coloured top bars for artists

This commit is contained in:
Josef Citrine 2016-07-17 01:22:59 +01:00
parent fa7eb96ea6
commit b98a776db7
12 changed files with 159 additions and 16 deletions

View file

@ -7,7 +7,9 @@
"url": "ssh://git@phabricator.poniverse.net/diffusion/PF/pony-fm.git"
},
"packages": {},
"dependencies": {},
"dependencies": {
"color-thief": "github:logic-dev/color-thief"
},
"devDependencies": {
"angular": "1.5.6",
"angular-chart.js": "1.0.0-alpha6",

View file

@ -1,7 +1,7 @@
<div class="resource-details artist-details" ng-class="::{'x-archived': artist.is_archived}">
<header ng-style="{'background-image': 'linear-gradient(180deg, ' + artist.avatar_colors[0] + ' 15%, ' + artist.avatar_colors[1] + ' 100%)'}">
<img src="{{artist.avatars.normal}}">
<header ng-style="headerStyle">
<img src="{{artist.avatars.normal}}" id="avatar">
<div class="artist-right">
<h1>{{artist.name}}<i class="material-icons admin-star" ng-show="::artist.isAdmin" data-title="Admin" bs-tooltip>verified_user</i></h1>
<p class="follower-count">
@ -11,7 +11,7 @@
'other': '{} followers'}">
</ng-pluralize>
</p>
<a href="#" class="btn btn-default" ng-class="{'btn-primary': !artist.user_data.is_following}" ng-show="auth.isLogged && auth.user.id != artist.id" pfm-eat-click ng-click="toggleFollow()">
<a href="#" class="btn btn-default btn-flat" ng-class="{'btn-primary': !artist.user_data.is_following}" ng-show="auth.isLogged && auth.user.id != artist.id" pfm-eat-click ng-click="toggleFollow()">
<span ng-if="!artist.user_data.is_following">Follow</span>
<span ng-if="artist.user_data.is_following">Following!</span>
</a>

View file

@ -42,6 +42,7 @@ require 'script!../base/marked'
require 'script!../base/moment'
require '../base/soundmanager2-nodebug'
require 'script!../base/tumblr'
require 'color-thief';
require 'angular-strap'
# Just ignore this, blame webpack
require '../../../../node_modules/angular-strap/dist/angular-strap.tpl'

View file

@ -42,7 +42,7 @@ module.exports = angular.module('ponyfm').controller "application", [
notifications.markAllAsRead()
$scope.notifActive = false
$scope.notifPulloutToggle = () ->
$scope.notifActive = !$scope.notifActive
@ -98,6 +98,9 @@ module.exports = angular.module('ponyfm').controller "application", [
$scope.notifActive = false
$scope.isPinnedPlaylistSelected = false
if oldState.name.indexOf('content.artist.') != -1 && newState.name.indexOf('content.artist.') == -1
$('.top-bar').css('background': '')
if newState.name == 'content.playlist'
$scope.isPinnedPlaylistSelected = playlists.isPlaylistPinned newParams.id

View file

@ -21,13 +21,144 @@ window.pfm.preloaders['artist'] = [
]
module.exports = angular.module('ponyfm').controller "artist", [
'$scope', 'artists', '$state', 'follow'
($scope, artists, $state, follow) ->
'$scope', 'artists', '$state', 'follow', '$rootScope'
($scope, artists, $state, follow, $rootScope) ->
updateArtist = (force = false) ->
artists.fetch($state.params.slug, force)
.done (artistResponse) ->
$scope.artist = artistResponse.artist
tempImg = document.createElement('img')
tempImg.setAttribute 'src', artistResponse.artist.avatars.small
tempImg.addEventListener 'load', ->
colorThief = new ColorThief();
palette = colorThief.getPalette(tempImg, 2)
$('.top-bar').css('background': selectHeaderColour(palette[0], palette[1]))
$scope.headerStyle = {'background-image': createGradient(palette[0], palette[1])}
$scope.$apply()
rgbArrayToCss = (array) ->
'rgb(' + array[0] + ',' + array[1] + ',' + array[2] + ')'
hslArrayToCss = (array) ->
'hsl(' + array[0] + ',' + array[1] + '%,' + array[2] + '%)'
dimColor = (colour) ->
hsl = rgbToHsl(colour)
if hsl[2] >= 50
hsl[2] = 50
if hsl[1] <= 20
hsl[1] = 30
return hslToRgb(hsl)
else
return colour
createGradient = (vib, dark) ->
if $(window).width() <= 480
'linear-gradient(180deg, ' + rgbArrayToCss(vib) + ' 5%, ' + rgbArrayToCss(dimColor(dark)) + ' 95%)'
else
'linear-gradient(170deg, ' + rgbArrayToCss(vib) + ' 15%, ' + rgbArrayToCss(dark) + ' 110%)'
findHighestSaturation = (hsl1, hsl2) ->
if hsl1[1] > hsl2[1]
return hsl1
else
return hsl2
findBestColour = (hsl1, hsl2) ->
maxLumin = 60
mid = 40
best = undefined
if Math.abs(hsl1[2] - mid) < Math.abs(hsl2[2] - mid)
best = hsl1
else
best = findHighestSaturation(hsl1, hsl2)
if best[2] > maxLumin
best[2] = maxLumin
return best
selectHeaderColour = (colour1, colour2) ->
hsl1 = rgbToHsl(colour1)
hsl2 = rgbToHsl(colour2)
out = rgbArrayToCss(hslToRgb(findBestColour(hsl1, hsl2)))
return out
rgbToHsl = (rgbArr) ->
r1 = rgbArr[0] / 255
g1 = rgbArr[1] / 255
b1 = rgbArr[2] / 255
maxColor = Math.max(r1, g1, b1)
minColor = Math.min(r1, g1, b1)
L = (maxColor + minColor) / 2
S = 0
H = 0
if maxColor != minColor
if L < 0.5
S = (maxColor - minColor) / (maxColor + minColor)
else
S = (maxColor - minColor) / (2.0 - maxColor - minColor)
if r1 == maxColor
H = (g1 - b1) / (maxColor - minColor)
else if g1 == maxColor
H = 2.0 + (b1 - r1) / (maxColor - minColor)
else
H = 4.0 + (r1 - g1) / (maxColor - minColor)
L = L * 100
S = S * 100
H = H * 60
if H < 0
H += 360
round = (value, decimals) ->
Number Math.round(value + 'e' + decimals) + 'e-' + decimals
[round(H, 6), round(S, 6), round(L, 6)]
toPercent = (amount, limit) ->
amount / limit
hueToRgb = (p, q, t) ->
if t < 0
t += 1
if t > 1
t -= 1
if t < 1 / 6
return p + (q - p) * 6 * t
if t < 1 / 2
return q
if t < 2 / 3
return p + (q - p) * (2 / 3 - t) * 6
p
hslToRgb = (bits) ->
rgb = []
v = undefined
q = undefined
p = undefined
hsl =
h: toPercent(parseInt(bits[0], 10) % 360, 360)
s: toPercent(parseInt(bits[1], 10) % 101, 100)
l: toPercent(parseInt(bits[2], 10) % 101, 100)
if hsl.s == 0
v = parseInt(Math.round(255 * hsl.l))
rgb[0] = v
rgb[1] = v
rgb[2] = v
else
q = if hsl.l < 0.5 then hsl.l * (1 + hsl.s) else hsl.l + hsl.s - (hsl.l * hsl.s)
p = 2 * hsl.l - q
rgb[0] = parseInt((hueToRgb(p, q, hsl.h + 1 / 3) * 256).toFixed(0), 10)
rgb[1] = parseInt((hueToRgb(p, q, hsl.h) * 256).toFixed(0), 10)
rgb[2] = parseInt((hueToRgb(p, q, hsl.h - (1 / 3)) * 256).toFixed(0), 10)
rgb
$scope.toggleFollow = () ->
follow.toggle('artist', $scope.artist.id).then (res) ->
$scope.artist.user_data.is_following = res.is_followed

View file

@ -236,6 +236,11 @@ html body {
&.btn-flat {
box-shadow: 0 0 0 transparent !important;
background-color: transparent;
&.btn-default:hover {
background-color: rgba(255, 255, 255, 0.5);
}
}
}

View file

@ -28,7 +28,7 @@
}
input.search-input {
background: lighten(@pfm-logo-purple, 10%);
background: rgba(255,255,255,0.15);
color: #fff;
border: 0;
font-size: 13px;

View file

@ -160,9 +160,10 @@
&.artist-details {
> header {
padding: 15px;
background-size: cover;
background-position: center;
padding: 25px;
margin: -15px -15px 10px;
> img {
width: 150px;
@ -229,7 +230,7 @@
> header {
padding: 5px;
background: #eee;
background: #ddd;
overflow: hidden;
margin-bottom: 10px;

View file

@ -18,7 +18,6 @@
@import 'https://fonts.googleapis.com/css?family=Material+Icons';
@import 'base/bootstrap/bootstrap';
@import 'base/font-awesome/font-awesome';
@import 'variables';
@import 'mixins';

View file

@ -89,7 +89,6 @@ header {
width: (@pfm-sidebar-size);
height: 64px;
line-height: 42px;
background: @pfm-logo-purple;
color: #fff;
font-size: 24pt;
font-weight: lighter;
@ -99,7 +98,7 @@ header {
position: relative;
&:hover {
background: darken(@pfm-logo-purple, 15%);
background: rgba(0,0,0,0.3);
color: #fff;
text-decoration: none;
}
@ -267,6 +266,7 @@ header {
height: @pfm-top-bar-size;
width: 100%;
top: 0;
transition: background 0.5s @swift-ease-in-out;
.material-shadow(1);
.burger-wrapper {

View file

@ -216,8 +216,8 @@
}
> header {
margin-bottom: 0px;
padding-bottom: 40px !important;
margin: 0 !important;
padding: 20px 0 40px !important;
> img {
float: none !important;

View file

@ -13,7 +13,8 @@ module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
jQuery: "jquery",
ColorThief: "color-thief"
}),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
],