Skip to content

Media Items

Dylan Fisher edited this page Jun 5, 2019 · 5 revisions

Points of Interest

Add points of interest to media items that allow background images to be positioned according to a central point on the image.

bin/rails generate migration AddPointOfInterestToMediaItems point_of_interest_x:float point_of_interest_y:float

# db/migrate/20190508182450_add_point_of_interest_to_media_items.rb

class AddPointOfInterestToMediaItems < ActiveRecord::Migration[6.0]
  def change
    add_column :media_items, :point_of_interest_x, :float, default: 50
    add_column :media_items, :point_of_interest_y, :float, default: 50
  end
end
<%# app/views/admin/media_items/_form.html.erb %>

<% if @media_item.image? %>
  <label>Point of Interest</label>
  <div id="media-item__point-of-interest" class="media-item__point-of-interest">
    <%= content_tag :div, nil, id: 'media-item__point-of-interest__crosshair', class: 'media-item__point-of-interest__crosshair', style: "top: #{@media_item.point_of_interest_y}%; left: #{@media_item.point_of_interest_x}%;" %>
    <%= image_tag @media_item.attachment.url(:medium) %>
    <%= f.input :point_of_interest_x, as: :hidden %>
    <%= f.input :point_of_interest_y, as: :hidden %>
  </div>
  <p class="help-block">Click the image to change the point of interest of the image. The point of interest is used to determine where to crop the image in some contexts.</p>
<% end %>
// app/assets/javascripts/forest/admin_partials/media_item_point_of_interest.js

$(document).on('click.mediaItemPointOfInterest', '#media-item__point-of-interest', function(e) {
  var $wrapper = $(this);
  var $inputX = $wrapper.find('#media_item_point_of_interest_x');
  var $inputY = $wrapper.find('#media_item_point_of_interest_y');
  var $point = $wrapper.find('#media-item__point-of-interest__crosshair');
  var parentOffset = $wrapper.offset();
  var parentWidth = $wrapper.width();
  var parentHeight = $wrapper.height();
  var x = Math.round( ( (e.pageX - parentOffset.left) / parentWidth * 100 ) * 10 ) / 10;
  var y = (e.pageY - parentOffset.top) / parentHeight * 100;

  $point.css({
    left: x + '%',
    top: y + '%'
  });

  $inputX.val(x);
  $inputY.val(y);
});

Style the point-of-interest input in the admin form

// app/assets/stylesheets/forest/admin_overrides.scss

.media-item__point-of-interest {
  position: relative;
}

.media-item__point-of-interest__crosshair {
  position: absolute;
  width: 40px;
  height: 40px;
  cursor: crosshair;
  transform: translate(-50%, -50%);
  user-select: none;

  &:before,
  &:after {
    content: '';
    position: absolute;
    background-color: white;
    box-shadow: 0 0 0 1px black;
  }

  &:before {
    width: 40px;
    height: 1px;
    top: 50%;
  }

  &:after {
    width: 1px;
    height: 40px;
    left: 50%;
  }
}

Set the background image's style in your views

<%= content_tag :div, style: "background-image: #{@media_item.attachment.url(:medium)}; background-position: #{@media_item.point_of_interest_x}% #{@media_item.point_of_interest_y}%;" %>
Clone this wiki locally