Практика обрезки изображений во внешнем интерфейсе

JavaScript
  • суг команда
  • Добавить Автора

Можно сказать, что в текущих интерфейсных проектах функция изображения очень распространена, например, отображение изображений, обрезка и редактирование изображений, загрузка изображений и т. Д., Тогда есть спрос на наш проект.

В настоящее время нам нужна функция для свободного редактирования изображений в нашем проекте.Когда могут появляться изображения, которые необходимо часто редактировать, и в то же время, когда мы обнаруживаем, что нас не устраивает обрезка и мы хотим провести точную настройку, мы обнаружится, что если мы будем обрабатывать картинки по обычным привычкам, например загружать на сервер после кадрирования или переводить в base64, что не соответствует требованиям. Так как с этим лучше поступить? Как решить сценарии приложений с минимальным количеством сетевых запросов и хранилища? Затем мы подумали о том, чтобы работать с нашими функциями только с чистыми данными.

Во-первых, Amway — это режущий артефакт, cropperjs, который я лично считаю простой в использовании библиотекой компонентов с полной настройкой и методами API.

Представленный в проекте, нельзя пропустить эталонный стиль

import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';

Здесь мы берем реакцию в качестве примера

this.state = {
  width: 640,   //图片展示宽
  height: 360,   //图片展示高   
  imgWidth: 640,   //图片实际宽
  imgHeight: 360,   //图片实际高
  imgLeft: 0,   //图片左偏移
  imgTop: 0,   //图片上偏移
  editing: false   //是否编辑中
}
//展示图片的基本dom结构,我们使用外div内img的形式,来跟数据结合控制裁剪图片的展示
const { width, height, imgWidth, imgHeight, imgLeft, imgTop, editing } = this.state;
const containerStyle = {
  width: `${width}px`,
  height: `${height}px`
}
const imgStyle = {
  width: `${imgWidth}px`,
  height: `${imgHeight}px`,
  left: `${imgLeft}px`,
  top: `${imgTop}px`
}

.img-container {
  overflow: hidden;
  position: relative;
}

.crop-img {
  position: absolute;
  left: 0;
  top: 0;
}
<div 
  className="img-container" 
  style={containerStyle}
>
  <img 
    className="crop-img"
    src={picture} 
    style={imgStyle} 
    alt="pic"
  ></img>
</div>

Проще говоря, внешний элемент управляет шириной и высотой кадрированного дисплея, сюда же навешивается позиционирование элемента согласно требованиям проекта, а внутренний img монтирует реальный размер и смещение изображения.

Инициализированный элемент cropperjs будет находиться на том же уровне DOM, что и объект инициализации img, то есть, если мы напрямую инициализируем отображение img, отображение области редактирования будет зависеть от родительского элемента, как показано на рисунке, это будет непросто просмотреть при увеличении изображения.

Так что здесь для свободы редактирования изображения рекомендуется отображать DOM и DOM, используемый для инициализации объекта кадрирования отдельно, здесь область редактирования - это, например, полный экран, и она настроена в соответствии с фактическим функционалом. площадь проекта.

.edit-container {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}

<div 
  className="img-container" 
  style={containerStyle}
>
  <img 
    className="crop-img"
    src={picture} 
    style={imgStyle} 
    alt="pic"
  ></img>
</div>

//cropper初始化
this.myRef = React.createRef();
this.myCropper = new Cropper(this.myRef.current, options);
//options配置
const options = {
    dragMode: 'move',   //使裁剪时图片可拖动
    background: false,  //因为我们现在是全屏可编辑,需要隐藏掉默认的背景
}
//当然还有许多常见的配置项,如编辑框尺寸比例等,大家可自行查看api

//裁剪保存
save() {
const cropBoxData = this.myCropper.getCropBoxData();    //获取裁剪框数据
const canvasData = this.myCropper.getCanvasData();      //获取图片数据
this.setState({
  width: cropBoxData.width,
  height: cropBoxData.height,
  imgLeft: canvasData.left - cropBoxData.left,
  imgTop: canvasData.top - cropBoxData.top,
  imgWidth: canvasData.width,
  imgHeight: canvasData.height
})
}

В этом случае мы можем полностью редактировать в настроенном полноэкранном режиме, а эффект сохранения выглядит следующим образом: здесь мы завершили первую часть функции, обрезав и сохранив данные и отобразив

Сосредоточьтесь на двух используемых нами API-методах, getCropBoxData и getCanvasData, getCanvasData используется для получения фактических данных картинки (текущая ширина и высота, и смещение смещения относительно видимой области родительского элемента), а getCropBoxData используется для получения данных, связанных с кадрированием, относительно области изображения.

Затем идут последующие требования.Как мы можем восстановить эффект, когда мы делаем второе редактирование?Ну, на самом деле, когда мы записывали данные отсечения, мы просто заново вычисляли соответствующее отношение данных, а затем инициализировали его.Добавить конфигурацию в варианты обрезки

const options = {
dragMode: 'move',
background: false,
//控件初始化后重置相应配置
ready: () => {
  const { width, height, imgWidth, imgHeight, imgLeft, imgTop } = this.state;
  //根据实际需要出现裁图功能进行定位,此处left和top仅为测试暂时默认值定义
  const left = 50;  
  const top = 50;
  this.myCropper.setCanvasData({
    width: imgWidth,
    height: imgHeight,
    left: left,
    top: top
  });
  this.myCropper.setCropBoxData({
    left: left - imgLeft,
    top: top - imgTop,
    width: width,
    height: height
  })
  
}
}
this.myCropper = new Cropper(this.myRef.current, options);

В это время мы снова нажимаем на обрезку, и она прекрасно восстанавливается.Разрыв между левой и верхней частью является верхней и левой частью setCanvasData, который можно настроить в соответствии с фактическим проектом.Слева и верхняя часть setCropBoxData относительно позиционирования обреза-канваса.форма расчета.

На этом основные функции закончились.Если он используется в редактировании h5 и предназначен для масштабирования, соответствующие расчеты данных должны включать значение масштабирования масштаба, иначе размер отображаемого изображения и редактируемого изображения не будут равны. условие. В то же время есть много функций, которые не будут отображаться, например, установка соотношения кадров обрезки, редактирование масштаба и т. д., попробуйте.

Конечно, если вы хотите сохранить изображение, есть также соответствующий метод обрезки данных изображения везде.

this.myCropper.getCroppedCanvas().toDataURL('image/jpeg')

Наконец, мы можем видеть, что во всем функциональном процессе все, что нам нужно, — это обрезанные данные, быстрое чтение и запись и отсутствие дополнительного хранилища изображений, что снижает накладные расходы и оптимизирует хранилище файлового сервера.

cropperjs гитхаб:Github.com/ Wind Far Toru ...

Спасибо за внимание, комментарии и исправления приветствуются.