2012-04-23 8 views
15

Tworzę "generator obrazów", w którym użytkownicy mogą przesłać obraz i dodać tekst i/lub narysować na nim. Obraz wyjściowy ma ustalony rozmiar (698x450).Jaka jest matematyka pod względem rozmiaru tła CSS: cover

Po stronie klienta, gdy użytkownik przesyła swój obraz, jest ustawiony jako tło elementu div o wymiarach 698x450 w rozmiarze tła: okładka. To sprawia, że ​​ładnie wypełnia to miejsce.

Ostateczny połączony obraz jest generowany przez PHP za pomocą funkcji GD. Moje pytanie brzmi: jak mogę uzyskać obraz w skali PHP w taki sam sposób jak w CSS. Chcę, aby wynik skryptu PHP wyglądał tak samo, jak gdyby obraz był ustawiony w CSS, tak jak był powyżej. Czy ktoś wie, w jaki sposób przeglądarki wykorzystujące rozmiar tła: okładka obliczyć, jak skalować obraz odpowiednio? Chcę przetłumaczyć to na PHP.

Dzięki

Odpowiedz

40

Oto logika kryjąca się za obliczeniami okładki.

Masz cztery wartości Base:

imgWidth // your original img width 
imgHeight 

containerWidth // your container width (here 698px) 
containerHeight 

Dwa wskaźniki pochodzące z tych wartości:

imgRatio = (imgHeight/imgWidth)  // original img ratio 
containerRatio = (containerHeight/containerWidth)  // container ratio 

Chcesz znaleźć dwa nowe wartości:

finalWidth // the scaled img width 
finalHeight 

sposób:

if (containerRatio > imgRatio) 
{ 
    finalHeight = containerHeight 
    finalWidth = (containerHeight/imgRatio) 
} 
else 
{ 
    finalWidth = containerWidth 
    finalHeight = (containerWidth/imgRatio) 
} 

... i masz odpowiednik tła-size: cover.

+10

Nie wiem, dlaczego, ale musiałem zmienić ostatnią linię jako 'finalHeight = (containerWidth * imgRatio)' aby działało poprawnie dla mojego kodu – Ergec

3

Podczas korzystania background-size: cover, jest skalowany do najmniejszego rozmiaru, który zakrywa całe tło.

Jeśli więc jest cieńszy niż jest wysoki, skaluj go, aż jego szerokość będzie taka sama jak powierzchnia. Tam, gdzie jest wyższy niż cienki, skaluj go, aż jego wysokość będzie taka sama jak powierzchnia.

Gdy jest większy niż obszar do pokrycia, przeskaluj go, aż znajdzie się w odpowiednim miejscu (w przypadku mniejszej wysokości przelewu, skaluj do tej samej wysokości, jeśli szerokość będzie mniejsza, przeskaluj aż do uzyskania tej samej szerokości).

3

Dzięki mdi za skierowanie mnie we właściwym kierunku, ale to nie wydawało się całkiem poprawne. Jest to rozwiązanie, które pracował dla mnie:

$imgRatio = $imageHeight/$imageWidth; 
    $canvasRatio = $canvasHeight/$canvasWidth; 

    if ($canvasRatio > $imgRatio) { 
     $finalHeight = $canvasHeight; 
     $scale = $finalHeight/$imageHeight; 
     $finalWidth = round($imageWidth * $scale , 0); 
    } else { 
     $finalWidth = $canvasWidth; 
     $scale = $finalWidth/$imageWidth; 
     $finalHeight = round($imageHeight * $scale , 0); 
    } 
2

wiem, że to jest bardzo stare pytanie, ale odpowiedź pisałem jest rzeczywiście czystsze za pomocą max i min w stosunkach między obrazami zamiast każdego obrazu z sam:

var originalRatios = { 
    width: containerWidth/imageNaturalWidth, 
    height: containerHeight/imageNaturalHeight 
}; 

// formula for cover: 
var coverRatio = Math.max(originalRatios.width, originalRatios.height); 

// result: 
var newImageWidth = imageNaturalWidth * coverRatio; 
var newImageHeight = imageNaturalHeight * coverRatio; 

Lubię to podejście, ponieważ jest bardzo systematyczne - może to niewłaściwe słowo -.Co mam na myśli to można pozbyć sprawozdania if i uczynić go pracować w bardziej „formuły matematyczne” rodzaju sposób (wejście = wyjście, jeśli to ma sens):

var ratios = { 
    cover: function(wRatio, hRatio) { 
    return Math.max(wRatio, hRatio); 
    }, 

    contain: function(wRatio, hRatio) { 
    return Math.min(wRatio, hRatio); 
    }, 

    // original size 
    "auto": function() { 
    return 1; 
    }, 

    // stretch 
    "100% 100%": function(wRatio, hRatio) { 
    return { width:wRatio, height:hRatio }; 
    } 
}; 

function getImageSize(options) { 
    if(!ratios[options.size]) { 
    throw new Error(size + " not found in ratios"); 
    } 

    var r = ratios[options.size](
    options.container.width/options.image.width, 
    options.container.height/options.image.height 
); 

    return { 
    width: options.image.width * (r.width || r), 
    height: options.image.height * (r.height || r) 
    }; 
} 

stworzyłem jsbinhere if chcesz rzucić okiem na to, co mam na myśli z systematyczny (to również ma metodę scale, które myślałem, że nie była potrzebna w tej odpowiedzi, ale bardzo przydatne dla czegoś innego niż zwykle).