mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2025-02-17 02:24:22 +01:00
Tweaked colour algorithm and updated notifications
This commit is contained in:
parent
1edc3e8992
commit
ea7345992e
4 changed files with 167 additions and 140 deletions
|
@ -21,13 +21,16 @@ window.pfm.preloaders['artist'] = [
|
|||
]
|
||||
|
||||
module.exports = angular.module('ponyfm').controller "artist", [
|
||||
'$scope', 'artists', '$state', 'follow', '$rootScope'
|
||||
($scope, artists, $state, follow, $rootScope) ->
|
||||
'$scope', 'artists', '$state', 'follow', '$rootScope', 'color'
|
||||
($scope, artists, $state, follow, $rootScope, color) ->
|
||||
updateArtist = (force = false) ->
|
||||
if force
|
||||
window.location.reload()
|
||||
|
||||
artists.fetch($state.params.slug, force)
|
||||
.done (artistResponse) ->
|
||||
$scope.artist = artistResponse.artist
|
||||
$scope.headerStyle = {'background-image': createGradient(artistResponse.artist.avatar_colors[0], artistResponse.artist.avatar_colors[1])}
|
||||
$scope.headerStyle = {'background-image': color.createGradient(artistResponse.artist.avatar_colors[0], artistResponse.artist.avatar_colors[1])}
|
||||
|
||||
tempImg = document.createElement('img')
|
||||
tempImg.setAttribute 'src', artistResponse.artist.avatars.small + '?' + new Date().getTime()
|
||||
|
@ -38,138 +41,9 @@ module.exports = angular.module('ponyfm').controller "artist", [
|
|||
colorThief = new ColorThief();
|
||||
palette = colorThief.getPalette(tempImg, 2)
|
||||
|
||||
$('.top-bar').css('background': selectHeaderColour(palette[0], palette[1]))
|
||||
$('.top-bar').css('background': color.selectHeaderColour(palette[0], palette[1]))
|
||||
$scope.$apply()
|
||||
|
||||
rgbArrayToCss = (array) ->
|
||||
'rgb(' + array[0] + ',' + array[1] + ',' + array[2] + ')'
|
||||
|
||||
hslArrayToCss = (array) ->
|
||||
'hsl(' + array[0] + ',' + array[1] + '%,' + array[2] + '%)'
|
||||
|
||||
hexToRgb = (hex) ->
|
||||
h = '0123456789ABCDEF'
|
||||
r = h.indexOf(hex[1]) * 16 + h.indexOf(hex[2])
|
||||
g = h.indexOf(hex[3]) * 16 + h.indexOf(hex[4])
|
||||
b = h.indexOf(hex[5]) * 16 + h.indexOf(hex[6])
|
||||
return [r,g,b]
|
||||
|
||||
dimColor = (colour) ->
|
||||
hsl = rgbToHsl(hexToRgb(colour))
|
||||
|
||||
if hsl[2] >= 50
|
||||
hsl[2] = 50
|
||||
if hsl[1] <= 20
|
||||
hsl[1] = 30
|
||||
return hslToRgb(hsl)
|
||||
else
|
||||
return hexToRgb(colour)
|
||||
|
||||
createGradient = (vib, dark) ->
|
||||
if $(window).width() <= 480
|
||||
'linear-gradient(180deg, ' + vib + ' 5%, ' + rgbArrayToCss(dimColor(dark)) + ' 95%)'
|
||||
else
|
||||
'linear-gradient(170deg, ' + vib + ' 15%, ' + 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
|
||||
|
|
150
resources/assets/scripts/app/services/color.coffee
Normal file
150
resources/assets/scripts/app/services/color.coffee
Normal file
|
@ -0,0 +1,150 @@
|
|||
# Pony.fm - A community for pony fan music.
|
||||
# Copyright (C) 2016 Josef Citrine
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
module.exports = angular.module('ponyfm').factory('color', [
|
||||
'$rootScope'
|
||||
($rootScope) ->
|
||||
self =
|
||||
rgbArrayToCss: (array) ->
|
||||
'rgb(' + array[0] + ',' + array[1] + ',' + array[2] + ')'
|
||||
|
||||
hslArrayToCss: (array) ->
|
||||
'hsl(' + array[0] + ',' + array[1] + '%,' + array[2] + '%)'
|
||||
|
||||
hexToRgb: (hex) ->
|
||||
h = '0123456789ABCDEF'
|
||||
r = h.indexOf(hex[1]) * 16 + h.indexOf(hex[2])
|
||||
g = h.indexOf(hex[3]) * 16 + h.indexOf(hex[4])
|
||||
b = h.indexOf(hex[5]) * 16 + h.indexOf(hex[6])
|
||||
return [r,g,b]
|
||||
|
||||
dimColor: (colour) ->
|
||||
hsl = self.rgbToHsl(self.hexToRgb(colour))
|
||||
|
||||
if hsl[2] >= 50
|
||||
hsl[2] = 50
|
||||
if hsl[1] <= 20
|
||||
hsl[1] = 30
|
||||
return self.hslToRgb(hsl)
|
||||
else
|
||||
return self.hexToRgb(colour)
|
||||
|
||||
createGradient: (vib, dark) ->
|
||||
if $(window).width() <= 480
|
||||
'linear-gradient(180deg, ' + vib + ' 5%, ' + self.rgbArrayToCss(self.dimColor(dark)) + ' 95%)'
|
||||
else
|
||||
'linear-gradient(170deg, ' + vib + ' 15%, ' + dark + ' 110%)'
|
||||
|
||||
findHighestSaturation: (hsl1, hsl2) ->
|
||||
if hsl1[1] > hsl2[1]
|
||||
return hsl1
|
||||
else
|
||||
return hsl2
|
||||
|
||||
findBestColour: (hsl1, hsl2) ->
|
||||
maxLumin = 50
|
||||
mid = 50
|
||||
best = undefined
|
||||
|
||||
if Math.abs(hsl1[2] - mid) < Math.abs(hsl2[2] - mid)
|
||||
best = hsl1
|
||||
else
|
||||
best = self.findHighestSaturation(hsl1, hsl2)
|
||||
|
||||
if best[2] > maxLumin
|
||||
best[2] = maxLumin
|
||||
|
||||
return best
|
||||
|
||||
selectHeaderColour: (colour1, colour2) ->
|
||||
hsl1 = self.rgbToHsl(colour1)
|
||||
hsl2 = self.rgbToHsl(colour2)
|
||||
out = self.rgbArrayToCss(self.hslToRgb(self.findBestColour(hsl1, hsl2)))
|
||||
return out
|
||||
|
||||
round: (value, decimals) ->
|
||||
Number Math.round(value + 'e' + decimals) + 'e-' + decimals
|
||||
|
||||
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
|
||||
|
||||
[self.round(H, 6), self.round(S, 6), self.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: self.toPercent(parseInt(bits[0], 10) % 360, 360)
|
||||
s: self.toPercent(parseInt(bits[1], 10) % 101, 100)
|
||||
l: self.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((self.hueToRgb(p, q, hsl.h + 1 / 3) * 256).toFixed(0), 10)
|
||||
rgb[1] = parseInt((self.hueToRgb(p, q, hsl.h) * 256).toFixed(0), 10)
|
||||
rgb[2] = parseInt((self.hueToRgb(p, q, hsl.h - (1 / 3)) * 256).toFixed(0), 10)
|
||||
|
||||
rgb
|
||||
self
|
||||
])
|
14
resources/assets/styles/content.less
vendored
14
resources/assets/styles/content.less
vendored
|
@ -641,18 +641,18 @@ html {
|
|||
|
||||
.notification-pullout {
|
||||
position: absolute;
|
||||
top: 64px;
|
||||
right: -410px;
|
||||
top: -450px;
|
||||
right: 10px;
|
||||
width: 400px;
|
||||
height: ~"calc(100% - 128px)";
|
||||
height: 500px;
|
||||
z-index: 500;
|
||||
background: #eee;
|
||||
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transform: translateX(0px) translateZ(0px);
|
||||
.material-shadow(2);
|
||||
transition: transform 0.3s @swift-ease-in-out;
|
||||
transform: translateY(0px) translateZ(0px);
|
||||
|
||||
&.active {
|
||||
transform: translateX(-410px) translateZ(0px);
|
||||
transform: translateY(520px) translateZ(0px);
|
||||
}
|
||||
|
||||
.notif-container {
|
||||
|
|
3
resources/assets/styles/mobile.less
vendored
3
resources/assets/styles/mobile.less
vendored
|
@ -347,7 +347,10 @@
|
|||
|
||||
.notification-pullout {
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 64px;
|
||||
width: 100%;
|
||||
height: ~"calc(100% - 128px)";
|
||||
transform: translateY(-120%) translateZ(0);
|
||||
|
||||
&.active {
|
||||
|
|
Loading…
Reference in a new issue