mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2025-02-19 19:34:23 +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", [
|
module.exports = angular.module('ponyfm').controller "artist", [
|
||||||
'$scope', 'artists', '$state', 'follow', '$rootScope'
|
'$scope', 'artists', '$state', 'follow', '$rootScope', 'color'
|
||||||
($scope, artists, $state, follow, $rootScope) ->
|
($scope, artists, $state, follow, $rootScope, color) ->
|
||||||
updateArtist = (force = false) ->
|
updateArtist = (force = false) ->
|
||||||
|
if force
|
||||||
|
window.location.reload()
|
||||||
|
|
||||||
artists.fetch($state.params.slug, force)
|
artists.fetch($state.params.slug, force)
|
||||||
.done (artistResponse) ->
|
.done (artistResponse) ->
|
||||||
$scope.artist = artistResponse.artist
|
$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 = document.createElement('img')
|
||||||
tempImg.setAttribute 'src', artistResponse.artist.avatars.small + '?' + new Date().getTime()
|
tempImg.setAttribute 'src', artistResponse.artist.avatars.small + '?' + new Date().getTime()
|
||||||
|
@ -38,138 +41,9 @@ module.exports = angular.module('ponyfm').controller "artist", [
|
||||||
colorThief = new ColorThief();
|
colorThief = new ColorThief();
|
||||||
palette = colorThief.getPalette(tempImg, 2)
|
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()
|
$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 = () ->
|
$scope.toggleFollow = () ->
|
||||||
follow.toggle('artist', $scope.artist.id).then (res) ->
|
follow.toggle('artist', $scope.artist.id).then (res) ->
|
||||||
$scope.artist.user_data.is_following = res.is_followed
|
$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 {
|
.notification-pullout {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 64px;
|
top: -450px;
|
||||||
right: -410px;
|
right: 10px;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
height: ~"calc(100% - 128px)";
|
height: 500px;
|
||||||
z-index: 500;
|
z-index: 500;
|
||||||
background: #eee;
|
background: #eee;
|
||||||
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
|
.material-shadow(2);
|
||||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: transform 0.3s @swift-ease-in-out;
|
||||||
transform: translateX(0px) translateZ(0px);
|
transform: translateY(0px) translateZ(0px);
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
transform: translateX(-410px) translateZ(0px);
|
transform: translateY(520px) translateZ(0px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notif-container {
|
.notif-container {
|
||||||
|
|
3
resources/assets/styles/mobile.less
vendored
3
resources/assets/styles/mobile.less
vendored
|
@ -347,7 +347,10 @@
|
||||||
|
|
||||||
.notification-pullout {
|
.notification-pullout {
|
||||||
left: 0;
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 64px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: ~"calc(100% - 128px)";
|
||||||
transform: translateY(-120%) translateZ(0);
|
transform: translateY(-120%) translateZ(0);
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
|
|
Loading…
Reference in a new issue