web-dev-qa-db-fra.com

Calcul des valeurs d'ombre pour toutes les élévations de Material Design

Dans la documentation la plus récente sur Material Design ( https://www.google.com/design/spec/what-is-material/elevation-shadows.html#elevation-shadows-elevation-Android- ), un ensemble exhaustif de Les éléments de l'interface utilisateur sont référencés avec leur élévation respective (z-index in dp). Par exemple, un switch est élevé par 1dp , alors qu'un dialogue est élevé par 24dp . Actuellement, la liste des éléments d'interface utilisateur de Google utilise 10 niveaux d'élévation différents. Puisque l'élévation décide de l'ombre de l'élément, nous aurons besoin de 10 ombres différentes. Et c'est là que je suis perdu.

Comment calculer/déduire les bonnes valeurs d'ombre (couleur, décalage x, décalage y, flou, étendue) pour chaque niveau d'élévation?

J'ai trouvé différentes sources qui ont calculé des valeurs d'ombre pour 5 altitudes différentes ( https://news.layervault.com/stories/42319-calculating-shadow-values-for-material-design ). Cependant, 5 marches d'élévation ne suffisent pas, elles ne donnent pas d'explication sur la manière dont elles sont parvenues à ces valeurs respectives.

18
Anthony Wijnen

Vous avez une bonne nouvelle! J'ai eu toutes les profondeurs d'ombre de la profondeur 1 à la profondeur 24. Je l’ai eu de Angular Material . J'espère que cela vous aiderait.

.md-whiteframe-1dp {
    box-shadow:  0px 1px 3px 0px rgba(0, 0, 0, 0.2),
    0px 1px 1px 0px rgba(0, 0, 0, 0.14),
    0px 2px 1px -1px rgba(0, 0, 0, 0.12); }
.md-whiteframe-2dp {
    box-shadow:  0px 1px 5px 0px rgba(0, 0, 0, 0.2),
    0px 2px 2px 0px rgba(0, 0, 0, 0.14),
    0px 3px 1px -2px rgba(0, 0, 0, 0.12); }
.md-whiteframe-3dp {
    box-shadow:0px 1px 8px 0px rgba(0, 0, 0, 0.2),
    0px 3px 4px 0px rgba(0, 0, 0, 0.14),
    0px 3px 3px -2px rgba(0, 0, 0, 0.12); }
.md-whiteframe-4dp {
    box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.2),
    0px 4px 5px 0px rgba(0, 0, 0, 0.14),
    0px 1px 10px 0px rgba(0, 0, 0, 0.12); }
.md-whiteframe-5dp {
    box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2),
    0px 5px 8px 0px rgba(0, 0, 0, 0.14),
    0px 1px 14px 0px rgba(0, 0, 0, 0.12); }
.md-whiteframe-6dp {
    box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2),
    0px 6px 10px 0px rgba(0, 0, 0, 0.14),
    0px 1px 18px 0px rgba(0, 0, 0, 0.12); }
.md-whiteframe-7dp {
    box-shadow: 0px 4px 5px -2px rgba(0, 0, 0, 0.2),
    0px 7px 10px 1px rgba(0, 0, 0, 0.14),
    0px 2px 16px 1px rgba(0, 0, 0, 0.12); }
.md-whiteframe-8dp {
    box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2),
    0px 8px 10px 1px rgba(0, 0, 0, 0.14),
    0px 3px 14px 2px rgba(0, 0, 0, 0.12); }
.md-whiteframe-9dp {
    box-shadow: 0px 5px 6px -3px rgba(0, 0, 0, 0.2),
    0px 9px 12px 1px rgba(0, 0, 0, 0.14),
    0px 3px 16px 2px rgba(0, 0, 0, 0.12); }
.md-whiteframe-10dp {
    box-shadow: 0px 6px 6px -3px rgba(0, 0, 0, 0.2),
    0px 10px 14px 1px rgba(0, 0, 0, 0.14),
    0px 4px 18px 3px rgba(0, 0, 0, 0.12); }
.md-whiteframe-11dp {
    box-shadow: 0px 6px 7px -4px rgba(0, 0, 0, 0.2),
    0px 11px 15px 1px rgba(0, 0, 0, 0.14),
    0px 4px 20px 3px rgba(0, 0, 0, 0.12); }
.md-whiteframe-12dp {
    box-shadow: 0px 7px 8px -4px rgba(0, 0, 0, 0.2),
    0px 12px 17px 2px rgba(0, 0, 0, 0.14),
    0px 5px 22px 4px rgba(0, 0, 0, 0.12); }
.md-whiteframe-13dp {
    box-shadow: 0px 7px 8px -4px rgba(0, 0, 0, 0.2),
    0px 13px 19px 2px rgba(0, 0, 0, 0.14),
    0px 5px 24px 4px rgba(0, 0, 0, 0.12); }
.md-whiteframe-14dp {
    box-shadow: 0px 7px 9px -4px rgba(0, 0, 0, 0.2),
    0px 14px 21px 2px rgba(0, 0, 0, 0.14),
    0px 5px 26px 4px rgba(0, 0, 0, 0.12); }
.md-whiteframe-15dp {
    box-shadow: 0px 8px 9px -5px rgba(0, 0, 0, 0.2),
    0px 15px 22px 2px rgba(0, 0, 0, 0.14),
    0px 6px 28px 5px rgba(0, 0, 0, 0.12); }
.md-whiteframe-16dp {
    box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.2),
    0px 16px 24px 2px rgba(0, 0, 0, 0.14),
    0px 6px 30px 5px rgba(0, 0, 0, 0.12); }
.md-whiteframe-17dp {
    box-shadow: 0px 8px 11px -5px rgba(0, 0, 0, 0.2),
    0px 17px 26px 2px rgba(0, 0, 0, 0.14),
    0px 6px 32px 5px rgba(0, 0, 0, 0.12); }
.md-whiteframe-18dp {
    box-shadow: 0px 9px 11px -5px rgba(0, 0, 0, 0.2),
    0px 18px 28px 2px rgba(0, 0, 0, 0.14),
    0px 7px 34px 6px rgba(0, 0, 0, 0.12); }
.md-whiteframe-19dp {
    box-shadow: 0px 9px 12px -6px rgba(0, 0, 0, 0.2),
    0px 19px 29px 2px rgba(0, 0, 0, 0.14),
    0px 7px 36px 6px rgba(0, 0, 0, 0.12); }
.md-whiteframe-20dp {
    box-shadow: 0px 10px 13px -6px rgba(0, 0, 0, 0.2),
    0px 20px 31px 3px rgba(0, 0, 0, 0.14),
    0px 8px 38px 7px rgba(0, 0, 0, 0.12); }
.md-whiteframe-21dp {
    box-shadow: 0px 10px 13px -6px rgba(0, 0, 0, 0.2),
    0px 21px 33px 3px rgba(0, 0, 0, 0.14),
    0px 8px 40px 7px rgba(0, 0, 0, 0.12); }
.md-whiteframe-22dp {
    box-shadow: 0px 10px 14px -6px rgba(0, 0, 0, 0.2),
    0px 22px 35px 3px rgba(0, 0, 0, 0.14),
    0px 8px 42px 7px rgba(0, 0, 0, 0.12); }
.md-whiteframe-23dp {
    box-shadow: 0px 11px 14px -7px rgba(0, 0, 0, 0.2),
    0px 23px 36px 3px rgba(0, 0, 0, 0.14),
    0px 9px 44px 8px rgba(0, 0, 0, 0.12); }
.md-whiteframe-24dp {
    box-shadow: 0px 11px 15px -7px rgba(0, 0, 0, 0.2),
    0px 24px 38px 3px rgba(0, 0, 0, 0.14),
    0px 9px 46px 8px rgba(0, 0, 0, 0.12); }
16
Scott Roa

Voici une fonction que j'ai créée qui donne un bon résultat, je crois:

(Javascript)

function getShadow(object, dp)
{
    if (dp <= 0)
    {
        panel.style.boxShadow = "none";
        return;
    }

    panel.style.boxShadow = "0px " + dp + "px " + dp + "px " + "rgba(0, 0, 0, .38)";
}

Un jfiddle: https://jsfiddle.net/crkb906z/

Fondamentalement, la distance de la couche de base est la distance par rapport au sommet de l'ombre, et j'utilise la même valeur pour le flou afin de la rendre plus floue à mesure que le matériau monte.

J'ai comparé le résultat de ceci aux 3 ombres utilisées par polymère et elles étaient très comparables. Étant donné que je ne parviens même pas à trouver une cohérence entre les 5 ombres de couche fournis par la plupart des gens, j'imagine que la façon dont les calculs sont calculés n'a pas cette importance.

MODIFIER

D'accord, après avoir étudié les ombres à paupières disponibles pour les 5 profondeurs (elles proviennent de ici , mais Google l'a depuis supprimée de la documentation), j'ai mis au point une formule plus complexe qui donne des ombres qui ont l'air beaucoup plus comme les exemples dans ce lien:

function applyShadow(element, dp)
{
    if (dp == 0)
    {
        element.style.boxShadow = "none";
    }
    else
    {
        var shadow = "0px ";

        var ambientY = dp;
        var ambientBlur = dp == 1 ? 3 : dp * 2;
        var ambientAlpha = (dp + 10 + (dp / 9.38)) / 100;

        shadow += ambientY + "px " + ambientBlur + "px rgba(0, 0, 0, " + ambientAlpha + "), 0px ";

        var directY = (dp < 10 ? (dp % 2 == 0 ? dp - ((dp / 2) - 1) : (dp - ((dp - 1) / 2))) : dp - 4);
        var directBlur = dp == 1 ? 3 : dp * 2;
        var directAlpha = (24 - Math.round(dp / 10)) / 100;

        shadow += directY + "px " + directBlur + "px rgba(0, 0, 0, " + directAlpha + ")";

        element.style.boxShadow  = shadow;
    }
}

Je mets à jour https://jsfiddle.net/crkb906z/1/ pour montrer la différence.

13
Troncoso

Voici la formule de Troncoso portée sur Stylus.

elevation(dp)
  if dp == 0
    box-shadow none
  else
    dp = unit(dp, px)
    blur = (dp == 1 ? 3 : dp * 2)
    amba = (dp + 10 + (dp / 9.38)) / 100
    diry = (dp < 10 ? (dp % 2 == 0 ? dp - ((dp / 2) - 1) : (dp - ((dp - 1) / 2))) : dp - 4)
    dira = (24 - (round(dp / 10))) / 100
    box-shadow 0px dp blur rgba(0, 0, 0, amba), 0px diry blur rgba(0, 0, 0, dira)
3
Joshua Kifer

Je ne fais que poster cette réponse car les informations officielles de Google relatives à l'altitude sur le Web MDC sont différentes de celles publiées jusqu'à présent.

Voici le fichier source à partir duquel je copie:

https://github.com/material-components/material-components-web/blob/e02b4c9fa2bd026c695f3a71efce58d01f460269/packages/mdc-elevation/_variables.scss

Valeurs box-shadow officielles de Google pour l'altitude (SASS mixin):

//
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.Apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

@import "@material/animation/variables";

$mdc-elevation-baseline-color: black;
$mdc-elevation-umbra-opacity: .2;
$mdc-elevation-penumbra-opacity: .14;
$mdc-elevation-ambient-opacity: .12;

$mdc-elevation-umbra-map: (
  0: "0px 0px 0px 0px",
  1: "0px 2px 1px -1px",
  2: "0px 3px 1px -2px",
  3: "0px 3px 3px -2px",
  4: "0px 2px 4px -1px",
  5: "0px 3px 5px -1px",
  6: "0px 3px 5px -1px",
  7: "0px 4px 5px -2px",
  8: "0px 5px 5px -3px",
  9: "0px 5px 6px -3px",
  10: "0px 6px 6px -3px",
  11: "0px 6px 7px -4px",
  12: "0px 7px 8px -4px",
  13: "0px 7px 8px -4px",
  14: "0px 7px 9px -4px",
  15: "0px 8px 9px -5px",
  16: "0px 8px 10px -5px",
  17: "0px 8px 11px -5px",
  18: "0px 9px 11px -5px",
  19: "0px 9px 12px -6px",
  20: "0px 10px 13px -6px",
  21: "0px 10px 13px -6px",
  22: "0px 10px 14px -6px",
  23: "0px 11px 14px -7px",
  24: "0px 11px 15px -7px"
);

$mdc-elevation-penumbra-map: (
  0: "0px 0px 0px 0px",
  1: "0px 1px 1px 0px",
  2: "0px 2px 2px 0px",
  3: "0px 3px 4px 0px",
  4: "0px 4px 5px 0px",
  5: "0px 5px 8px 0px",
  6: "0px 6px 10px 0px",
  7: "0px 7px 10px 1px",
  8: "0px 8px 10px 1px",
  9: "0px 9px 12px 1px",
  10: "0px 10px 14px 1px",
  11: "0px 11px 15px 1px",
  12: "0px 12px 17px 2px",
  13: "0px 13px 19px 2px",
  14: "0px 14px 21px 2px",
  15: "0px 15px 22px 2px",
  16: "0px 16px 24px 2px",
  17: "0px 17px 26px 2px",
  18: "0px 18px 28px 2px",
  19: "0px 19px 29px 2px",
  20: "0px 20px 31px 3px",
  21: "0px 21px 33px 3px",
  22: "0px 22px 35px 3px",
  23: "0px 23px 36px 3px",
  24: "0px 24px 38px 3px"
);

$mdc-elevation-ambient-map: (
  0: "0px 0px 0px 0px",
  1: "0px 1px 3px 0px",
  2: "0px 1px 5px 0px",
  3: "0px 1px 8px 0px",
  4: "0px 1px 10px 0px",
  5: "0px 1px 14px 0px",
  6: "0px 1px 18px 0px",
  7: "0px 2px 16px 1px",
  8: "0px 3px 14px 2px",
  9: "0px 3px 16px 2px",
  10: "0px 4px 18px 3px",
  11: "0px 4px 20px 3px",
  12: "0px 5px 22px 4px",
  13: "0px 5px 24px 4px",
  14: "0px 5px 26px 4px",
  15: "0px 6px 28px 5px",
  16: "0px 6px 30px 5px",
  17: "0px 6px 32px 5px",
  18: "0px 7px 34px 6px",
  19: "0px 7px 36px 6px",
  20: "0px 8px 38px 7px",
  21: "0px 8px 40px 7px",
  22: "0px 8px 42px 7px",
  23: "0px 9px 44px 8px",
  24: "0px 9px 46px 8px"
);

/**
 * The css property used for elevation. In most cases this should not be changed. It is exposed
 * as a variable for abstraction / easy use when needing to reference the property directly, for
 * example in a `will-change` rule.
 */
$mdc-elevation-property: box-shadow !default;

/**
 * The default duration value for elevation transitions.
 */
$mdc-elevation-transition-duration: 280ms !default;

/**
 * The default easing value for elevation transitions.
 */
$mdc-elevation-transition-timing-function: $mdc-animation-standard-curve-timing-function !default;

Voici une fonction Vanilla ES6 elevation que j'ai construite en fonction de ce qui précède:

const umbraColor = 'rgba(0, 0, 0, 0.2)';
const penumbraColor = 'rgba(0, 0, 0, 0.14)';
const ambientColor = 'rgba(0, 0, 0, 0.12)';


const umbra = [
  "0px 0px 0px 0px",
  "0px 2px 1px -1px",
  "0px 3px 1px -2px",
  "0px 3px 3px -2px",
  "0px 2px 4px -1px",
  "0px 3px 5px -1px",
  "0px 3px 5px -1px",
  "0px 4px 5px -2px",
  "0px 5px 5px -3px",
  "0px 5px 6px -3px",
  "0px 6px 6px -3px",
  "0px 6px 7px -4px",
  "0px 7px 8px -4px",
  "0px 7px 8px -4px",
  "0px 7px 9px -4px",
  "0px 8px 9px -5px",
  "0px 8px 10px -5px",
  "0px 8px 11px -5px",
  "0px 9px 11px -5px",
  "0px 9px 12px -6px",
  "0px 10px 13px -6px",
  "0px 10px 13px -6px",
  "0px 10px 14px -6px",
  "0px 11px 14px -7px",
  "0px 11px 15px -7px"
];

const penumbra = [
  "0px 0px 0px 0px",
  "0px 1px 1px 0px",
  "0px 2px 2px 0px",
  "0px 3px 4px 0px",
  "0px 4px 5px 0px",
  "0px 5px 8px 0px",
  "0px 6px 10px 0px",
  "0px 7px 10px 1px",
  "0px 8px 10px 1px",
  "0px 9px 12px 1px",
  "0px 10px 14px 1px",
  "0px 11px 15px 1px",
  "0px 12px 17px 2px",
  "0px 13px 19px 2px",
  "0px 14px 21px 2px",
  "0px 15px 22px 2px",
  "0px 16px 24px 2px",
  "0px 17px 26px 2px",
  "0px 18px 28px 2px",
  "0px 19px 29px 2px",
  "0px 20px 31px 3px",
  "0px 21px 33px 3px",
  "0px 22px 35px 3px",
  "0px 23px 36px 3px",
  "0px 24px 38px 3px"
];

const ambient = [
  "0px 0px 0px 0px",
  "0px 1px 3px 0px",
  "0px 1px 5px 0px",
  "0px 1px 8px 0px",
  "0px 1px 10px 0px",
  "0px 1px 14px 0px",
  "0px 1px 18px 0px",
  "0px 2px 16px 1px",
  "0px 3px 14px 2px",
  "0px 3px 16px 2px",
  "0px 4px 18px 3px",
  "0px 4px 20px 3px",
  "0px 5px 22px 4px",
  "0px 5px 24px 4px",
  "0px 5px 26px 4px",
  "0px 6px 28px 5px",
  "0px 6px 30px 5px",
  "0px 6px 32px 5px",
  "0px 7px 34px 6px",
  "0px 7px 36px 6px",
  "0px 8px 38px 7px",
  "0px 8px 40px 7px",
  "0px 8px 42px 7px",
  "0px 9px 44px 8px",
  "0px 9px 46px 8px"
];

export default (z) => (
  `
    box-shadow: ${umbra[z]} ${umbraColor},
                ${penumbra[z]} ${penumbraColor},
                ${ambient[z]} ${ambientColor};
  `
);
1
anthonator

Material Design Lite de Google m'a procuré des ombres. Je pense que ce code pourrait aider.

.shadow--2dp {
    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}

.shadow--3dp {
    box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 1px 8px 0 rgba(0, 0, 0, 0.12);
}

.shadow--4dp {
    box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
}

.shadow--6dp {
    box-shadow: 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1px rgba(0, 0, 0, 0.2);
}

.shadow--8dp {
    box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.2);
}

.shadow--16dp {
    box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2);
}

.shadow--24dp {
    box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2);
}
1
Scott Roa

Voici un port légèrement modifié pour Sass:

@mixin shadow($dp: 1) {
    @if $dp == 0 { box-shadow: none; }
    @else {
        $blur: if($dp == 1, 3, $dp * 2);
        $amba: ($dp + 11) / 100;
        $diry: $dp - floor($dp / 4);
        $dirb: floor(($dp + 5) / 2);
        $dira: (24 - (round($dp / 10))) / 100;
        box-shadow: 0px #{$dp + 'px'} #{$blur + 'px'} rgba(0, 0, 0, $amba), 0px #{$diry + 'px'} #{$dirb + 'px'} rgba(0, 0, 0, $dira);
    }
}
0
Spencer

Il existe une bibliothèque scss pour cela: SCSS-Material-Shadows

Voici la démo

Vous pouvez regarder le calcul complet dans le fichier scss.

La principale utilisation est un mixin appelé mdElevation(). mdElevationElement() est une implémentation pratique des valeurs d’altitude prédéfinies pour tous les éléments Matériau trouvés ici

Pour l'effet dynamique lors de la transition d'élévation, vous pouvez ajouter mdElevationTransition() dans votre scss. En tant que paramètre, utilisez le delta entre deux élévations. 

Pour plus d'informations détaillées, visitez la page github.

0
FaustmannChr